Exporting XLIFF files from Loco to your platform
For examples of importing XLIFF files into Loco, see XLIFF imports.
Loco provides numerous different flavours of XLIFF to cater for the significant differences across platforms that have adopted it. The following can be appended to all Export API endpoints to produce platform specific XLIFF files:
format=xcode
— See Xcode exampleformat=symfony
— See Symfony exampleformat=angular
— See Angular example- Without format — See Generic example
There are some additional export options that aren't documented with the cross-platform parameters. These don't appear in the dashboard interface, but can be used directly with the Export API in the query string:
xlf-version
— Switches between versions1.2
and2.0
of the XLIFF schemas, see XLIFF 2 example.xlf-original
— Forces theoriginal
attribute for the default<file>
section (when no other value applies).xlf-no-resname
— Disables use of theresname
orname
attribute, preferring theid
attribute for translation keys.
XLIFF 1.2
The default way to export XLIFF is to specify the .xlf
file extension with no format parameter. This will produce a generic XLIFF 1.2 file, as follows:
curl -u <your_key>: https://localise.biz/api/export/locale/fr.xlf
<xliff version="1.2">
<file source-language="en" target-language="fr">
<body>
<trans-unit id="loco:5e84b2c5fb3e4935312b6d32" resname="greeting">
<source>Hello World</source>
<target>Bonjour tout le monde</target>
<note>This is a welcome message for the home page</note>
</trans-unit>
</body>
</file>
</xliff>
This export does not target any platform in particular and as such it tries to follow the XLIFF specification in as general a way as possible without adding too many features that may be unrecognised by other software.
The example above shows the resname
attribute, which according to the XLIFF 1.2 specification might reference "the key in the key/value pair in a Java properties file, the ID of a string in a Windows string table, the index value of an entry in a database table, etc...". The id
attribute here is an internal identifier generated by Loco. It is present to ensure the translation unit can be re-imported into Loco even if the resource name was to change.
You can change this behaviour by appending the xlf-no-resname
parameter, which forces the Asset ID to populate the id
attribute instead.
XLIFF 2.0
You can specify your preferred version of the XLIFF schema using the xlf-version
parameter, which will produce the semantically equivalent XLIFF 2.0 version of the above, as follows:
curl -u <your_key>: https://localise.biz/api/export/locale/fr.xlf?xlf=version=2
<xliff version="2.0" srcLang="en" trgLang="fr">
<file>
<unit id="loco:5e84b2c5fb3e4935312b6d32" name="greeting">
<notes>
<note>This is a welcome message for the home page</note>
</notes>
<segment state="translated">
<source>Hello World</source>
<target>Bonjour tout le monde</target>
</segment>
</unit>
</file>
</xliff>
There is little to choose between these versions, except that XLIFF 2.0 is an ISO standard and is often preferred for that reason if not for any particular enhancements it has over its predecessor.
As per XLIFF 1.2, you can append xlf-no-resname
to populate the id
attribute instead of the name
attribute if that is preferred.
Xcode
Specifying format=xcode
will export a version of XLIFF 1.2 targeting Xcode. This enables some specific features and quirks, as in these examples:
curl -u <your_key>: https://localise.biz/api/export/locale/fr.xlf?format=xcode
<xliff version="1.2" xml:space="preserve">
<file original="example.xcstrings" source-language="en" target-language="fr" datatype="plaintext">
<body>
<trans-unit id="greeting">
<source>Hello World</source>
<target>Bonjour tout le monde</target>
<note>This is a welcome message for the home page</note>
</trans-unit>
</body>
</file>
</xliff>
The XML above shows that the resname
attribute is absent. Instead the id
attribute holds the string key used by Xcode.
Specifying format=xcode
is also required for exporting platform-specific string variations. Here's a simple example of a pluralized string:
<xliff version="1.2">
<file original="example/Localizations/Localizable.xcstrings" source-language="en" target-language="fr">
<body>
<trans-unit id="apple|==|plural.one">
<source>%d apple</source>
<target>%d pomme</target>
</trans-unit>
<trans-unit id="apple|==|plural.other">
<source>%d apples</source>
<target>%d pommes</target>
</trans-unit>
</body>
</file>
</xliff>
The XML above shows how an asset called apple
is referenced from a .xcstrings
file, with its plural variations identified after the |==|
separator.
Prior to Xcode 15, plurals were managed via separate .strings
and .stringsdict
files.
Loco switches between these structures depending on the original file reference. Legacy output for .strings
files looks like this:
<xliff version="1.2">
<file original="example/en.lproj/Localizable.strings" source-language="en" target-language="fr">
<body>
<trans-unit id="apple" translate="no">
<source>%d apple</source>
<target></target>
</trans-unit>
</body>
</file>
<file original="example/en.lproj/Localizable.stringsdict" source-language="en" target-language="fr">
<body>
<trans-unit id="/apple:dict/NSStringLocalizedFormatKey:dict/:string">
<source>%#@value@</source>
<target>%#@value@</target>
</trans-unit>
<trans-unit id="/apple:dict/value:dict/one:dict/:string">
<source>%d apple</source>
<target>%d pomme</target>
</trans-unit>
<trans-unit id="/apple:dict/value:dict/other:dict/:string">
<source>%d apples</source>
<target>%d pommes</target>
</trans-unit>
</body>
</file>
</xliff>
The XML above shows the plural variations linked via the .stringsdict
file section. (Notice the original
attribute of the <file>
elements).
The primary apple
unit in the first section serves only as a reference into the main strings table. The actual translations are taken from the second section.
Note that the legacy stringsdict
system is still the default for assets without a file reference (i.e. they weren't imported from a xcstrings
or XLIFF file).
You can override the default file reference by specifying the xlf-original
parameter in the query string. This works for all XLIFF exports;
See also:
Symfony
Specifying format=symfony
will export a version of XLIFF 1.2 targeting Symfony. This supports Symfony's particular usage of translation keys as in the following example:
curl -u <your_key>: https://localise.biz/api/export/locale/en.xlf?format=symfony
<xliff version="1.2">
<file original="file.ext" source-language="en" target-language="en">
<body>
<trans-unit id="loco:5e84c933484636643e2a5702">
<source>greeting</source>
<target>Hello World</target>
</trans-unit>
</body>
</file>
</xliff>
The example above shows that in the source language export the <source>
element holds the translation key and the <target>
element holds the full source text.
The resname
attribute is purposefully absent to save redundant duplication. This is fully compatible with the Symfony XLIFF loader.
If you prefer XLIFF 2.0, a Symfony-specific file can be produced as follows (here exporting French):
curl -u <your_key>: 'https://localise.biz/api/export/locale/fr.xlf?format=symfony&xlf-version=2'
<xliff version="2.0" srcLang="en" trgLang="fr">
<file original="file.ext" id="f1">
<unit id="loco:5e84cb078faae82e96750152">
<segment>
<source>hello</source>
<target>Bonjour tout le monde</target>
</segment>
</unit>
</file>
</xliff>
See also:
Angular
Appending format=angular
enables some Angular-specific use of the XLIFF format, in particular the use of <note>
elements which is not strictly prescribed by the XLIFF specification.
curl -u <your_key>: 'https://localise.biz/api/export/locale/fr.xlf?format=angular'
<xliff version="1.2">
<file original="ng.template" source-language="en" target-language="fr">
<body>
<trans-unit id="greeting" datatype="html">
<source>Hello World</source>
<target>Bonjour tout le monde</target>
<note priority="1" from="description">This is a sample greeting</note>
<note priority="1" from="meaning">User welcome</note>
</trans-unit>
</body>
</file>
</xliff>
The example above shows the context property ("User welcome") is exported into a <note>
element and is differentiated from the descriptive note above it.
According to the Angular documentation the meaning is not just metadata, but contributes to a message's uniqueness so must be preserved throughout the translation process.
If you prefer XLIFF 2.0, an Angular-specific file can be produced as follows with identical meaning:
curl -u <your_key>: 'https://localise.biz/api/export/locale/fr.xlf?format=angular&xlf-version=2'
<xliff version="2.0" srcLang="en" trgLang="fr">
<file original="ng.template" id="ngi18n">
<unit id="greeting">
<notes>
<note category="description">This is a sample greeting</note>
<note category="meaning">User welcome</note>
</notes>
<segment>
<source>Hello World</source>
<target>Bonjour tout le monde</target>
</segment>
</unit>
</file>
</xliff>
See also Importing Angular XLIFF files.