---
title: "What does a localization workflow with XLIFF files look like?"
description: "Extract source strings into one XLIFF file per target language with your framework's tool, send the files to a CAT tool or TMS, get them back with filled <target> elements and translated states, and import them. Keep ids stable so re-extraction preserves translations."
category: xliff
date: 2026-10-09
canonical: https://localizely.com/i18n-questions/xliff/what-does-a-localization-workflow-with-xliff-files-look-like/
---

# What does a localization workflow with XLIFF files look like?

Extract, translate, import, repeat. The text stays owned by your code or string catalog; XLIFF is the exchange format that carries each string with its id and context to the translators and brings the translation back.

1. Extract with the framework's own tool, so ids and placeholders match what the runtime expects. Xcode's Product > Export Localizations writes an `.xcloc` catalog per language with the XLIFF inside. Angular's `ng extract-i18n` writes `messages.xlf`, which you copy to `messages.de.xlf` and so on. Symfony's `php bin/console translation:extract --force de` writes `translations/messages.de.xlf`. The result is one file per target language with `source-language` and `target-language` on `<file>`. Untranslated units have no `<target>`, an empty one, or `<target state="new">`; Symfony fills new targets with a `__` prefix unless you pass `--no-fill`.
2. Translate in a CAT tool or TMS. The translator fills `<target>` and the tool records progress in the `state` attribute (`translated`, then `signed-off` or `final`) or with `approved="yes"` on the `<trans-unit>`. Placeholders such as `<x id="INTERPOLATION"/>` are protected tags there, which is the main reason not to translate XLIFF in a text editor.
3. Import. Xcode's Product > Import Localizations reads the catalog back into the project; Angular reads the per-locale file named in `angular.json` at build time; Symfony loads `translations/` at runtime. Xcode and Angular match translation units by `id`, so re-importing updates existing translations instead of duplicating them.

Rules that keep this working round after round:

- Keep `id` values stable between exports. Angular's generated ids are derived from the source text and meaning, so a text change makes a new id and orphans the old translation; give units a custom id (`i18n="@@welcomeTitle"`) and never change ids in translation files, as the Angular docs say. Xcode uses the string key as the id.
- Use `resname` and `<note>` for context. `resname` carries the resource name (the key) when the id is synthetic; `<note>` carries developer comments, which is where Xcode puts the `comment:` text and Angular puts the description and meaning. Translators see both in their tool.
- Never edit `<source>` in a translated file. The next extraction overwrites it, and translation memory matches on the source text; change the string in code and re-extract.
- Keep the XLIFF files in version control next to the code. Every release then has a reviewable snapshot and a bad import is one revert away.
- Re-extract before each round and let the tool diff by id: unchanged units keep their translations, changed sources come back for review, removed units disappear.

Source: https://localizely.com/i18n-questions/xliff/what-does-a-localization-workflow-with-xliff-files-look-like/
