I want Django to localize all dates (in all regions), but I don't want translations. It seems like for a date to be put into the right locale, we need to add its language to LANGUAGES.
For dates to be localized, we also need USE_I18N = True and USE_L10N = True.
Is this even possible?
I don't want translations, because as long as the site is not fully translated, you will have a website that is only half-translated. This is an issue due to django, because its error messages are all translated.
The best approach for you is to store your data in your database as unix timestamps and then display them using javascript. This immidiately eliminates all the complex code you have for detecting the user's locale in django. With javascript it's a lot easier to do that, and also to display the time using the appropriate format.
toLocaleDateString is your friend
The toLocaleDateString() method returns a string with a language
sensitive representation of the date portion of this date. The new
locales and options arguments let applications specify the language
whose formatting conventions should be used and allow to customize the
behavior of the function. In older implementations, which ignore the
locales and options arguments, the locale used and the form of the
string returned are entirely implementation dependent.
Related
I'd like to ask you if you can briefly and in plain English explain to me
how cleaned_data() function validates data ?
Reason for asking is that I'm designing a web app powered by Django
and initially I thought cleaned_data() is smart enough to block user's input that contains potentially harmful characters. Such as ' ; < > and alike. Characters that can be used for SQL injection attacks.
To my surprise, when I deliberately slipped few of those characters into form field, the input made it to database. I was quite shocked.
So then ... what the cleaned_data() function is good for ?
I read about this function in docs, however I couldn't find necessarily answer to this.
cleaned_data is for validated form data. If you have a required CharField, for example, it will validate whether it is present, and whether it has enough characters. If you have an EmailField, then it will validate that it includes an email address.
Take a look at some of the build in form fields for a better idea of what you can do.
It is not intended to prevent XSS or SQL injection. It simply confirms that your form follows basic rules that you have set for it.
You missunderstood cleaned_data. The simplest definition of cleaned_data is something like:
A dict that contains data entered by the user after various validation
(built-in or custom)
Now, that being said, to understand every steps to form validation refer to this link (re-inventing the wheel would be silly since it is greatly explained.)
As for the SQL injection, this is another problem. But again, Django as a built-in way of handling it, this is from the documentation:
By using Django’s querysets, the resulting SQL will be properly
escaped by the underlying database driver. However, Django also gives
developers power to write raw queries or execute custom sql. These
capabilities should be used sparingly and you should always be careful
to properly escape any parameters that the user can control. In
addition, you should exercise caution when using extra() and RawSQL..
I can totally see your confusion, but remember that they are two different things.
What's the sanest way to handle translation and localization of dynamic lists?
Let's say I've queried the database, and got a list ["Foos", "Bars", "Bazes"]. Let's also assume the list always contain at least two items - I'll be sure to use a different translation for the single-item case.
What should I do if I need a phrase like "We have a wide choice of Foos, Bars and Bazes in our code"? (assuming that list items are dynamic so I can't just pre-translate all the possible permutations, and need to do things at runtime.)
I see at least the following issues:
I need to inflect all the items to the correct form (are there languages where different forms are required depending on the position in the list?)
Different locales may have drastically different rules how to join items.
E.g. CJK locales need "、" instead of ",".
And AFAIK in Chinese there will be "及" or "和" - depending on the full phrase - before the last item, so I guess there's some ambiguity with translating "and".
And, as I've read, some languages may avoid punctuation like it's used in English, but have other concepts instead, e.g. Arabic translator may prefer use "و" before every item (although they also have commas, "،"). Not sure if true or not - I don't know Arabic, just saw it mentioned.
My problem is, I don't even know what tooling may help me here. I don't have any particular programming language requirements, although Python or JavaScript would be the best. But I guess I can run just about anything, as I can probably build a l10n microservice and query it from my project.
I've used GNU gettext before I've encountered this, but I haven't found anything that would help me in its APIs and data formats. The best I can imagine is _("We have a wide choice of %s in our code", list_text) and generate list_text using some DIY hacks. I'm not sure XLIFF format has anything like this as well. I've found i18n-list-generator on npm but it's way too simplicistic.
Have anyone dealt with something like this? What did you do? Is there any library out there that handles this - so I can take a look at its API and learn how it does things?
Here's how I would approach it:
No concatenation. All string joining needs to be done via format strings with placeholders.
Only use format strings that support named/numbered placeholders. E.g. {FOO} or $1 instead of %s (this is to allow for parameter reordering). Named placeholders are also better since they give more context to translators. Let's assume we're using {FOO}-style placeholders.
To render a list, I would use a couple of format strings, e.g.: joinItem = "{LIST}, {ITEM}" to append items to the list and joinLastItem = "{LIST} and {ITEM}" to append the last item. This will allow one to render strings like Foos, Bars and Bases, change punctuation and even reverse the ordering of the list, if necessary.
Finally, you can use the final format string, e.g. weHaveTheseItems = "We have a wide choice of {ITEMS} in our code", assuming the {ITEMS} gets replaced with the previously rendered string.
Shameless self-promotion: you may want to have a look at the Plurr library that supports such {FOO}-style placeholders, as well as plurals (something you will likely need for such messages). It supports JavaScript among other languages.
This is a pain, as you point out not all locales can be expected to support the ",,,,and" form.
Inspired by #GSerg and #Igor Afanasyev I came up with a GNU Gettext based solution like the following (pseudo gettext invocation):
GettextPlural(
// TRANSLATORS: For multiple "choices", each will be prefixed with a new-line (\n)
"We have a wide choice of {choices} in our code",
"In our code we have a wide choice of{choices}", choices.Count)
should print like:
"We have a wide choice of FOOs in our code"
"In our code we have a wide choice of
FOOs
BARs
BAZs"
Remember to stick the --add-comments=TRANSLATORS to your xgettext invocation.
For Web purposes you could use <ul><li>...</li>... </ul> or whatever instead of \n.
The benefit is that layout is at least as universal as UI layout, but you are still allowing non-English'ish locale plural forms.
Some languages have only one plural form so their translation must work with both a single choice and multiple choices, so in particular, they cannot have a conditional new-line.
In Rails 4 (which supports multilingual inflections), I can set:
config.i18n.default_locale = :es
in my config/application.rb, which allows me to do stuff like this in the console:
'general'.pluralize(:es) => "generales"
But when I run:
rails g model General conciencia:string atencion:string
Rails generates files with 'general' pluralized as 'generals' which in spanish should be 'generales'
Shouldn't Rails be using the multilingual inflector for its generators if the locale is set? Is there a way to force it to use them?
Thanks!
A bit late, but for the record: There's an argument in a Rails issue about why is it this way (so it's no a bug, but you can discuss it about):
Source: https://github.com/rails/rails/issues/10125#issuecomment-17274499
Up to Rails 4, the inflector had no support for multiple locales.
There was only one set of rules. The application has a default locale,
and in a i18n application each request may have a different locale,
but that didn't affect the inflector.
The inflector is not only used by the application, it is also used by
the framework to convert paths to class names, class names to tables,
create method names dynamically for the associations API, etc.
Obviously, those computations cannot vary. If your schema has a
"regions" table, Active Record has to map the Region class always to
the "regions" table, no matter the evolution of the application
(unless the schema changes, but the schema has to be visualized as
mostly static regarding to this, much more static that a configuration
option).
I have worked on applications that started development using :en, get
i18ned, and then switch to a default locale of :es. The locale is
something that affects the interface in that mindset. Everything
internal should work as it did before.
You should be able to change the default locale and everything else in
a way that does not affect static things like association names,
tables, routes, etc.
In could be the case that you have i18n routes (which change with the
locale of the request), but in general the statement above should be
true.
In order to be as backwards compatible as possible, we have left the
framework untouched, and have made the inflections to have a default
of :en so that existing applications get the same mappings after an
upgrade.
As you can see, django-pagination has polish (pl) translations - https://github.com/ericflo/django-pagination/tree/master/pagination/locale but I dont know, how to set polish language for django-pagination? (default english)
This should happen automatically.
Check your django settings if USE_I18N is set to True and if your LANGUAGE_CODE is set to pl.
For further information take a look at the django localization page. You can find a more detailed documentation of how the translation in django works here.
There's also a list of language codes, I guess pl should be correct.
You can either change the language setting of your browser, which will send the appropriate headers with each request and trigger the translation to be used, or you can provide a language setting selection so the user can choose their language.
You can roll your own code to provide this interface or use django-user-accounts.
You also might want to check that you have the appropriate middleware installed as described in this documenation.
I'm using BabelDjango to format dates and times in templates. Babel comes with some predefined formats called "short", "long", and "full". I know you can also just pass in your custom format like "DDD mmm" etc, but I would like to create a few more named formats. This would be much easier to spread a few different standard formats throughout my app.
is this possible? can I add more to Babel, or is it best to create my own tag filters in django?
Thanks!
Unfortunately defining custom aliases for date formats is not possible (yet) in Babel. The existing format names are taken from the CLDR database so they are pretty static at the moment.
I suggest you write you a wrapper function which translates your alias to a Babel date pattern.
Btw: Which date formats do you need?
Btw2: The Babel users mailing list is a good place to ask such questions (and likely you'll get faster answers).