Main menu

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:

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 versions 1.2 and 2.0 of the XLIFF schemas, see XLIFF 2 example.
  • xlf-original — Forces the original attribute for the default <file> section (when no other value applies).
  • xlf-no-resname — Disables use of the resname or name attribute, preferring the id 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.

Last updated by