Bundles¶
- class django_ftl.bundles.Bundle(files, default_locale=None, require_activate=False, use_isolating=True)¶
Create a bundle from a list of files.
- Parameters:
list(str) (files) –
Files are specified as relative paths that start from a specific locale directory.
For example, if you are writing
myapp
, and you havemyapp/locales/en/myapp/main.ftl
for English andmyapp/locales/de/myapp/main.ftl
for German, then you would pass["myapp/main.ftl"]
which will refer to either of these files depending on the active language.If multiple paths are given, they will be added in order. This means that if later files contain the same message IDs as earlier files, the later definitions will shadow and take precedence over earlier ones.
default_locale (str) – You may pass keyword argument
default_locale
(as a BCP47 string e.g. “en-US”), which will be used as a fallback if an unavailable locale is activated, or if a message ID is not found in the current locale. By default, yourLANGUAGE_CODE
setting will be used if nothing is passed (see Django docs for LANGUAGE_CODE).require_activate (bool) – By default the
default_locale
will be used as a fallback if no language has been activated. By passingrequire_activate=True
,format()
will raise an exception if you attempt to use it without first activating a language. This can be helpful to ensure that all code paths that use Bundles are setting a language first, and especially for ensuring that all module level uses of aBundle
useformat_lazy()
instead offormat()
.use_isolating (bool) – Controls whether substitutions in messages should be surrounded with bidi isolation characters. Defaults to
True
. PassFalse
to disable this (if, for example, all your text and substitutions are in scripts that go in the same direction).auto_reload (bool) –
Controls whether the Bundle will attempt to detect changes in
FTL
files and reload itself. If nothing is passed, automatic behavior will be used, which is:settings.AUTO_RELOAD_BUNDLES
if it is set, otherwise:True
ifsettings.DEBUG == True
and pyinotify is installedFalse
otherwise.
functions (dict) – A dictionary of custom functions that will be made available to messages in the bundle, as per the fluent-compiler docs on Custom Functions.
- format(message_id, args=None)¶
Generate a translation of the message specified by the message ID, in the currently activated locale.
args
is an optional dictionary of parameters for the message. These will normally be:strings
integers or floating point numbers (which will be formatted according to locale rules)
datetime objects (which will be formatted according to locale rules)
To specify or partially specify your own formatting choices for numbers and datetime objects, see the
fluent_compiler
docs for fluent_compiler.types.fluent_number and fluent_compiler.types.fluent_datetime.The arguments passed in may also be strings or numbers that are used to select variants.
Error handling in Bundle¶
Fluent’s philosophy is that in general, when generating translations, something
is usually better than nothing, and therefore it attempts to recover as much as
possible from error conditions. For example, if there are syntax errors in
.ftl
files, it will try to find as many correct messages as possible and
pass over the incorrect ones. Or, if a message is formatted but it is missing an
argument, the string '???'
will be used rather than turning the whole
message into an error of some kind. At the same time, these errors should be
reported somehow.
django-ftl in general follows the same principle. This means that things like
missing .ftl
files are tolerated, and most Bundle
methods rarely throw
exceptions.
Instead, when errors occur they are collected and then logged. Errors found in
.ftl
message files, or generated at runtime due to bad arguments, for
example, will be logged at ERROR
level using the stdlib logging framework, to
the django_ftl.message_errors
logger. Ensure that these errors are visible
in your logs, and this should make these problems more visible to you.
If a message is missing entirely, for instance, you will get '???'
returned
from Bundle.format
rather than an exception (but the error will be logged).
If the message is missing from the requested locale, but available in the
default locale, the default will be used (but you will still get an error
logged). Therefore, you don’t need to add try
/ except
around calls to
Bundle.format
to provide a fallback, because that is done for you.
There are some places where django-ftl does throw exceptions, however. These include:
Bundle.format
: If any of the bundle’s specified.ftl
are missing from the default locale, adjango_ftl.bundles.FileNotFoundError
exception will be raised. It is assumed that such a problem with the default locale is a result of a typo, rather than just a locale than has not been fully translated yet, and so the developer is warned early. An empty.ftl
file at the correct path is sufficient to silence this error.Bundle.format
: Ifrequire_activate
is True, this method will raise adjango_ftl.bundles.NoLocaleSet
exception if you attempt to use it before callingactivate
. This is a deliberate feature to help flush out cases where you are usingBundle.format()
before setting a locale, instead ofBundle.format_lazy()
.
These are deliberately intended to cause crashes, because you have a developer error that should cause failure as early and as loudly as possible.