Symfony/Propel: i18n tables - internationalization

i have this schema and fixtures:
sedi:
_attributes: { isI18N: true, i18nTable: sediI18n }
id: ~
sediI18n:
id: { type: integer, required: true, primaryKey: true, foreignTable: sedi, foreignReference: id }
culture: { isCulture: true, type: varchar, size: 7, required: true, primaryKey: true }
paese_indirizzo: { type: varchar(6), required: true }
indirizzo: { type: varchar(1024), required: true }
Sedi:
sede_roma_1: { }
SediI18n:
sede_roma_1_italiano: { id: sede_roma_1, culture: it, paese_indirizzo: eu, indirizzo: "Ufficio di Roma 1 Testaccio Via Galvani, 17 Roma - 00153 Italia" }
sede_roma_1_francese: { id: sede_roma_1, culture: fr, paese_indirizzo: eu, indirizzo: "Rome Office 1: Testaccio Via Galvani, 17 Roma - 00153 Italia" }
I'm trying to show in a template only the sede in Italian language ("Ufficio di Roma") but it shows also the sede in French language..
In that template I have write var_dump($sf_user->getCulture()) and prints "it".
Any idea?

I suggest you stay with the conventions and use lowercase characters and underscores for the table names. In fact, you don't have to write much code to get I18N support. What should be enough:
sedi:
id:
sedi_i18n:
paese_indirizzo: { type: varchar(6), required: true }
indirizzo: { type: varchar(1024), required: true }
Adapt your fixtures accordingly.

Related

GatsbyJS and Netlfiy string vs number in markdown

I'm having trouble with a datetime field in gatsby.
Originally I just used the string widget in netlify cms but markdown couldn't seem to decide what is a number and what's a string:
Which means gatsby sees conflicting field types:
warn There are conflicting field types in your data.
MarkdownRemark.frontmatter.startTime:
- type: number
value: 1080
- type: string
value: '07:00'
MarkdownRemark.frontmatter.endTime:
- type: number
value: 1140
- type: string
value: '08:00'
So I explicitly define them with the createTypes action as per gatsby's suggestion:
schema.buildObjectType({
name: 'Frontmatter',
fields: {
startTime: {
type: 'Date',
// resolve(parent){
// console.log(parent.startTime);
// },
extensions: {
dateformat: {
formatString: "HH:mm",
},
},
},
endTime: {
type: 'Date',
extensions: {
dateformat: {
formatString: "HH:mm",
},
}
},
},
}),
But that produces either 00:00 or "Invalid date"
I use the netlify timepicker to set the values:
- { label: "Start Time", name: startTime, widget: datetime, date_format: false, time_format: HH:mm, format: HH:mm}
- { label: "End Time", name: endTime, widget: datetime, date_format: false, time_format: HH:mm, format: HH:mm}
Is there a way I can force markdown to see strings instead of numbers? Or to see a datetime? Or get netlify cms to always save it as a string?
I have also had this problem and have discovered that the version of the YAML parser used by Gatsby (currently js-yaml#3.14.1) is parsing strings as base60 where possible. Which I believe is not compliant with the YAML 1.2 spec.
This issue has since been fixed in version 4 but unfortunately the libraries that Gatsby uses still depend on version 3. gatsby-transformer-remark#4.3.0 -> gray-matter#4.0.3 -> js-yaml#3.14.1
An attempt to force upgrade using npm-force-resolutions did not work but
fortunately gray-matter allow engines to be swapped using the options. Also gatsby-transformer-remark allows the gray-matter options to be configured within gatsby-config.js.
So I have managed to workaround the issue by installing js-yaml#4.1.0 and overriding the engine like so:
package.json
{
...
"dependencies": {
+ "js-yaml": "4.1.0",
gatsby-config.js
+ const yaml = require('js-yaml');
...
{
resolve: "gatsby-transformer-remark",
options: {
+ engines: {
+ yaml: {
+ parse: yaml.load.bind(yaml),
+ stringify: yaml.dump.bind(yaml)
+ }
},

Kendo-Grid column field validation

I am working on populating kendo--grid with APIs data but on adding validation on one field is automatically working for every other fields too.
Here is schema inside kendo-dataSource :
schema: {
model: {
id : "id",
fields: {
id: { editable: false, type: 'number'},
name: { editable: true, type : "string" },
unique_url: { editable: true , type: 'string'},
image_url : { editable: true, type : "string" },
title: {type : "string", validation: {
required: true,
validateTitle: function (input) {
console.log("I am inside validation",input.val());
if (input.val().length > 5) {
input.attr("data-validateTitle-msg", "Max length exceeded 5 characters only");
return false;
}
return true;
}
}
},
body: { editable: true, type : "string",validation: { max: 90, required: true, message : "Maximum characters should be 90"} },
adaccount_id: { editable: false, type: 'number'}
}
}
},
Here I have added validation for title field but its getting called for others fields too.
I am adding one snapshot of validation---
Please help me to find errors in it.
There isn't really any error in your code, but more like an error in Kendo Grid's validation design. Even though you specify the validation function only in the title field, it will run the validation globally for any input field that you edit.
In validateTitle you need to filter which input you want the validating function to run on. Something like this:
if (input.is("[name='title']") && input.val().length > 5) {
input.attr("data-validateTitle-msg", "Max length exceeded 5 characters only");
return false;
}
If you need a live working demo, you can always refer to Telerik's online demos that are editable, very handy for playing around with things. Here's the demo for custom validation where they similarly have to filter the input for the field name.
you want simply required field validation means just add your view model property attributes
[Required(ErrorMessage ="CountryCode is Mandatory")]
public virtual string CountryCode
{
get;
set;
}
We can easily set the maximum length using this code,It will not allow user to enter more characters than the specified one
model: {
id: "CLASSID",
fields: {
CLASSID: { type: "number" },
CLSNAME: { type: "string" },
CLSFLAG: {
type: "string", validation: {
required: true,maxlength:"3"
}
},
CLSSTATUS: { type: "boolean" }
}
}

Propel orm 1.6, symfony 1.4 embeded I18N form

I use propelorm (propel 1.6) plugin and symfony 1.4.20.
I have book table with I18n, and this book have relation with gallery table which also have I18n. I fill all book form fields, added two gallery images, filled all images fields. Click on save - it seems all ok: book fields are ok, first and second image have been uploaded, but only first image have filled i18n fields, second image all i18n fields are empty. What's the prob ?
(there's no redeclared doSave(), save(), bind() and other form methods)
schema:
book:
id: ~
title: { type: varchar(255), required: true }
author: { type: varchar(255), required: true }
description: { type: longvarchar, required: true }
sortable_rank: { type: integer, required: true }
is_active: { type: boolean, default: 1 }
_indexes:
active_sort: [ is_active, sortable_rank ]
_propel_behaviors:
sortable:
rank_column: sortable_rank
i18n:
i18n_columns: [title, description, author]
locale_column: culture
locale_alias: culture
default_locale: en
book_gallery:
id: ~
book_id: { type: integer, foreignTable: book, foreignReference: id, required: true, onDelete: cascade }
title: { type: varchar(255), required: true }
image: { type: varchar(255), required: true }
_propel_behaviors:
i18n:
i18n_columns: [title]
locale_column: culture
locale_alias: culture
default_locale: en
book form:
$languages = LanguageQuery::create()->getAllAsArray(); // returns like array('en' => 'english', ...);
$this->embedI18n(array_keys($languages));
$this->widgetSchema->setLabels($languages);
$this->embedRelation('BookGallery', array(
'title' => 'Application book store list',
'item_pattern' => 'Application book store %index%',
));
book gallery form:
$languages = LanguageQuery::create()->getAllAsArray(); // same as in book form
$this->embedI18n(array_keys($languages));
$this->widgetSchema->setLabels($languages);

symfony/propel: question about i18nTable and modules generated in the backend

in Jobeet there is this part below of the schema:
jobeet_category:
_attributes: { isI18N: true, i18nTable: jobeet_category_i18n }
id: ~
jobeet_category_i18n:
id: { type: integer, required: true, primaryKey: true, foreignTable: jobeet_category, foreignReference: id }
culture: { isCulture: true, type: varchar, size: 7, required: true, primaryKey: true }
name: { type: varchar(255), required: true }
slug: { type: varchar(255), required: true }
I have created the corresponding modules in the backend, but when i try to create a new "jobeet_category_i18n" i miss the select that would permit choose a "jobeet_category" object.
Anyway i try to create it, but as i expected an error message that speaks about the foreign key is showed.
Is that schema ok? why is not showed the select to choose a "jobeet_category" object?
Javi
http://www.symfony-project.org/forms/1_4/en/08-Internationalisation-and-Localisation#chapter_08_propel_objects_internationalization

Doctrine Sluggable Behavior for Foreign Relations

I have a database design case which I am curios whether Doctrine ORM supports it out-of-box.
Product:
columns:
id: {type: integer, primary: true, autoincrement: true }
type_id: { type: integer, notnull: true }
brand_id: { type: integer, notnull: true }
relations:
ProductType:
class: ProductType
local: type_id
foreign: id
Brand:
class: Brand
local: brand_id
foreign: id
ProductType:
actAs:
I18n:
fields: { name }
columns:
id: {type: integer, primary: true, autoincrement: true }
name: { type: string(255), notnull: true }
Brand:
actAs:
I18n:
fields: { name }
columns:
id: {type: integer, primary: true, autoincrement: true }
name: { type: string(255), notnull: true }
I want to slugify Products table, ie. products will be reached via their slugs. However, as you see both brand and productype tables has i18n behaviour. And moreover, product doesnt have a name. A product's slug will be: "Brand.name - ProductType.name", and vary with the language served.
For this scenario, is there anyway I can use Sluggable behaviour of Doctrine to sluggify my products automatically. Or do I have to manage it manually?
By the way my environment configuration is:
Doctrine Version: 1.2
Symfony: 1.4.1
Thanks
My understanding is that you need to have the slug in both Product Type and Brand models. You can leave the Product definition as it is. Anyway, I'm assuming from your question that there is only one product for every brand+type (even if it doesn't have to much sense). So ProductType and Brand will be defined like this:
schema.yml
----------
ProductType:
actAs:
I18n:
fields: { name }
actAs:
Sluggable: { fields: [name], uniqueBy: [lang], canUpdate: true }
columns:
...
Then you have to configure your Product route to use the slugs. And after that you will need to configure the action to check what you are getting from the route.
For example, this could be your route for Products:
routing.yml
-----------
product:
url: /:sf_culture/product/:brand_slug/:type_slug
param: { module: product, action: view }
requirements:
sf_culture: (?:en|fr)
sf_method: get
Then in the action you will call to your own findOneBySlugs($brand_slug, $type_slug) method:
product/actions/actions.class.php
---------------------------------
public function executeView(sfWebRequest $request)
{
$product = Doctrine::getTable('Product')
->findOneBySlugs(
$request->getParameter('brand_slug'),
$request->getParameter('type_slug')
);
$this->forward404Unless($product);
}
the problem with that solution are the queries. With:
$product = Doctrine::getTable('Product')
->findOneBySlugs(
$request->getParameter('brand_slug'),
$request->getParameter('type_slug')
);
you are doing a 5-join query if I'm not mistaken. You can improve to do only three (product, brand_translation and producttype_translation)
I'm in a similar situation, and the best option is to create a slug for each product using the brand or product type name in this case. So you would only need:
$product = Doctrine::getTable('Product')
->findOneBySlug($request->getParameter('slug'));
I'm thinking between two options:
Product:
actAs:
Sluggable:
unique: true
fields: [title]
builder: [Slug, slugify]
or using the getUniqueSlug() function on the record class. I think the first option is best so you don't have to worry about uniqueness.

Resources