---
title: "Entrega e intercambio"
description: "Puntos de entrada del SDK para importar y exportar libros y TMX, además de instantáneas de archivos de locale y las rutas que verbatra resuelve por locale."
type: "reference"
---
# Entrega e intercambio

Puntos de entrada del SDK para importar y exportar libros y TMX, además de instantáneas de archivos de locale y las rutas que verbatra resuelve por locale.

<SdkAnchorForward />

## Instantáneas de archivos de locale [#instantáneas-de-archivos-de-locale]

Los bloques con los que se construye un watcher de actualización en vivo como el de Studio: captura el
estado de un archivo de locale y luego cuenta qué cambió desde entonces.

### readLocaleFileSnapshot [#readlocalefilesnapshot]

<AvailableFrom version="0.5.0" />

Lee un archivo de locale (el locale de origen o cualquier locale de destino) y lo reduce a un hash de
contenido por clave. Un archivo que todavía no existe se lee como una instantánea vacía en lugar de
lanzar.

```ts title="Firma"
function readLocaleFileSnapshot(
  input: ReadLocaleFileSnapshotInput,
  deps?: ReadLocaleFileSnapshotDeps,
): Promise<LocaleFileSnapshot>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `locale` | `string` | yes | The locale file to snapshot. Unlike most entry points this is not checked against the configured target locales, so the source locale can be snapshotted too. |
| `cwd` | `string` | no | Directory the `files.pattern` is resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |

**Devuelve:** `LocaleFileSnapshot`

**Lanza:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_path_collision)

Devuelve `{ locale, hashes }`.

### diffLocaleSnapshots [#difflocalesnapshots]

<AvailableFrom version="0.5.0" />

Compara dos instantáneas del mismo archivo, tomadas en momentos distintos, y cuenta las claves añadidas,
modificadas y eliminadas entre ambas. Una función síncrona normal: `diffLocaleSnapshots(previous,
current)` devuelve `{ added, changed, removed }`. Solo contadores, nunca nombres de claves.

```ts title="Firma"
function diffLocaleSnapshots(
  previous: LocaleFileSnapshot,
  current: LocaleFileSnapshot,
): LocaleSnapshotDelta;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `locale` | `string` | yes | The locale this snapshot was taken for. |
| `hashes` | `ReadonlyMap<string, string>` | yes | Content hash per key, in the order the adapter read them. |

**Devuelve:** `LocaleSnapshotDelta`

## Rutas de locale [#rutas-de-locale]

### createLocalePathResolver [#createlocalepathresolver]

<AvailableFrom version="0.7.0" />

Resuelve la correspondencia entre locales y rutas del proyecto en ambos sentidos, a partir de
`files.pattern`, los locales configurados y `files.localeStyle`. `createLocalePathResolver(cwd,
config)` devuelve `{ pathFor, localeFor }`: `pathFor(locale)` es la ruta absoluta del archivo de un
locale, y `localeFor(path)` es el locale al que pertenece una ruta, o `undefined` para una ruta que
este proyecto no posee, y siempre `undefined` para un formato de catálogo compartido como `apple-xcstrings`. Todos los puntos de entrada del SDK resuelven rutas a través de él, así que
un watcher o un panel construido sobre el SDK ve exactamente las rutas que escribe una ejecución.

```ts title="Firma"
function createLocalePathResolver(
  cwd: string,
  config: LocalePathResolverConfig,
): LocalePathResolver;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `sourceLocale` | `string` | yes | The source locale, which some styles spell differently from the targets. |
| `targetLocales` | `readonly string[]` | yes | Every target locale. All of them are mapped up front so collisions are caught immediately. |
| `format` | `FormatId` | yes | The configured format. Every format maps each locale to a distinct path except a shared-catalogue format (one holding every locale in a single file, such as `apple-xcstrings`), which maps every locale to the same path. A `custom:` format is always treated as one file per locale. Under the `posix` locale style, the `gettext-po` format also spells a script the gettext way (`sr-Latn` as `sr@latin`) rather than the ICU way (`sr_Latn`). |
| `files` | `object` | yes | The file layout. |

**Devuelve:** `LocalePathResolver`

**Lanza:** [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_path_collision)

Todas las comprobaciones se ejecutan al crear el resolver, antes de leer ningún archivo: un patrón
y un estilo que no se pueden combinar, o un locale para el que el estilo no tiene una escritura
correcta, lanzan `LOCALE_LAYOUT_INVALID`, y dos locales que resuelven a la misma ruta lanzan
`LOCALE_PATH_COLLISION`.

## El par del libro [#el-par-del-libro]

La entrega para traductores humanos, como libro de Excel o como texto delimitado; consulta [Traducción humana](https://verbatra.kreitz-webdev.de/es/docs/manual-translation.md).

### exportWorkbook [#exportworkbook]

<AvailableFrom version="0.2.0" />

Escribe las cadenas que todavía necesitan traducción (claves faltantes y modificadas por locale; añade
las sin cambios con `includeUnchanged`) en un libro `.xlsx` con estilos. Las filas llevan la misma señal
de revisión que calcula una ejecución de translate. Sin llamada al proveedor, sin escritura del bloqueo.

```ts title="Firma"
function exportWorkbook(
  input: ExportWorkbookInput,
  deps?: ExportWorkbookDeps,
): Promise<ExportWorkbookResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `cwd` | `string` | no | Directory the `files.pattern` and `out` are resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `out` | `string` | no | Where to write the handoff. Defaults to DEFAULT_WORKBOOK_PATH for `xlsx` and to DEFAULT_DELIMITED_PATH for the delimited and XLIFF formats. Refused with `EXPORT_OUTPUT_CONFLICT`, before anything is read or written, when it resolves outside `cwd`, or when it or a file the export would write names a configured locale file, the lock file, the provenance file, the translation-memory cache, a file verbatra searches for its configuration, the ExportWorkbookInput.configPath file, or the ExportWorkbookInput.glossaryPath file. For `xlsx` it is also refused when it names no file (including one ending in a path separator) or names `cwd` itself; a delimited or XLIFF export may write into `cwd`. Names are compared case-insensitively, and, when the file-system port implements `realpath`, again after symbolic links are resolved, so a link cannot carry the handoff anywhere a plain path could not. |
| `configPath` | `string` | no | The configuration file `config` was loaded from, absolute or relative to `cwd`. It is refused as the output path even when its name is not one verbatra searches for. |
| `glossaryPath` | `string` | no | The glossary file the config names, absolute or relative to `cwd`, normally the `path` of a file-backed LoadedConfig.glossary. It is refused as the output path. |
| `locales` | `readonly string[]` | no | Restrict the export to these target locales. Defaults to every configured target locale. |
| `includeUnchanged` | `boolean` | no | Include keys that are already up to date, not just the missing and stale ones. Useful when a translator needs the surrounding context to translate consistently. Defaults to false. |
| `format` | `ExchangeFormat` | no | The handoff shape to write. Defaults to `xlsx`. |

**Devuelve:** `ExportWorkbookResult`

**Lanza:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#unknown_format), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_path_collision), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#source_invalid), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#lock_file_invalid), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#unknown_locale), [`EXPORT_OUTPUT_CONFLICT`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#export_output_conflict), [`EXPORT_UNWRITABLE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#export_unwritable)

**Ejemplo:** [El ciclo de ida y vuelta del libro](https://verbatra.kreitz-webdev.de/es/docs/programmatic-api.md#el-ciclo-de-ida-y-vuelta-del-libro)

`format` es `xlsx` por
defecto; `csv` y `tsv` escriben en su lugar un `<locale>.csv` o `<locale>.tsv` por locale, así que `out`
nombra un directorio para ellos (creado si falta) y una ruta de archivo para `xlsx`. `out` es por
defecto `DEFAULT_WORKBOOK_PATH` (`verbatra-translations.xlsx`) o, para los formatos
delimitados y XLIFF, `DEFAULT_DELIMITED_PATH` (`verbatra-translations`), ambos exportados como constantes. Los valores aceptados se exportan como `EXCHANGE_FORMATS` y el valor por defecto como `DEFAULT_EXCHANGE_FORMAT`, para que una herramienta que envuelve el SDK pueda validar un argumento de formato sin fijar la lista en el código. Devuelve `{ path, locales }`: la ruta
absoluta escrita y un número de filas por locale.

Antes de leer nada, `EXPORT_OUTPUT_CONFLICT` rechaza un `out` que queda fuera de `cwd`, y uno que,
por sí mismo o a través de un archivo que la exportación escribiría dentro, nombra un archivo de
locale configurado, el archivo de bloqueo, el archivo de procedencia, la caché de memoria de
traducción, un archivo que verbatra busca para su configuración, el archivo `configPath` o el
archivo `glossaryPath`, sin distinguir mayúsculas de minúsculas y, cuando `deps.fs` implementa
`realpath` como el valor por defecto, otra vez tras resolver los enlaces simbólicos. Una ruta
`xlsx` también se rechaza cuando no nombra ningún archivo (también una que termina en un separador
de ruta) o nombra el propio `cwd`; un directorio `csv`, `tsv` o XLIFF puede ser `cwd`. Una escritura que
falla, porque el directorio no es escribible, hay un directorio o un archivo en medio o el disco
está lleno, lanza `EXPORT_UNWRITABLE` con el archivo y el código del sistema de archivos en el
mensaje, y el error del sistema de archivos como `cause`.

<AvailableFrom version="0.12.0" />

`format: "xliff2"` y `format: "xliff12"` escriben para una herramienta TAO un `<locale>.xlf` en XLIFF 2.0 o 1.2 por locale en el directorio `out`: una unidad por clave, los marcadores de posición y el marcado como códigos en línea `<ph>` protegidos, la descripción y el significado de la clave como notas, el hash de origen en los metadatos de la unidad y un estado de segmento según el estado de bloqueo y de revisión (`initial` para una clave ausente o desactualizada, `translated` si está al día, `reviewed` si está aprobada). Se exportan los dos tipos, y `XliffFormat` nombra los dos miembros XLIFF de `ExchangeFormat`. Consulta [Entregar a una agencia de traducción](https://verbatra.kreitz-webdev.de/es/docs/translation-agency.md).

Cada unidad con destino lleva además su origen: XLIFF 1.2 califica un destino de clase máquina sin aprobar con `state-qualifier="mt-suggestion"`, y XLIFF 2.0 añade las entradas `origin` y `review-state` al grupo de metadatos `verbatra` de la unidad. El resultado lleva entonces también `provenanceMarkers`: `"written"`, o `"unavailable"` cuando no se pudo leer el archivo de procedencia y no se escribió ninguna marca. Consulta [Evidencia de traducción automática](https://verbatra.kreitz-webdev.de/es/docs/provenance-evidence.md#marcas-en-las-exportaciones).

### importWorkbook [#importworkbook]

<AvailableFrom version="0.2.0" />

Lee un libro rellenado de vuelta a los archivos de locale, ejecutando las mismas comprobaciones de
desfase del origen e integridad que `translate`. Solo las filas aceptadas avanzan su
línea base del bloqueo; una fila en blanco o rechazada se sigue exportando hasta que se resuelve de
verdad.

```ts title="Firma"
function importWorkbook(
  input: ImportWorkbookInput,
  deps?: ImportWorkbookDeps,
): Promise<RunSummary>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `workbook` | `string` | yes | Path to the filled handoff. For a delimited or XLIFF import the path is tried as a single file first, so one individual `<locale>.<csv\|tsv\|xlf>` file can be imported on its own, with the locale taken from its file name. A single XLIFF file whose name is not a configured target locale is matched by the target language it declares instead. If no file exists there, the path is treated as the directory the per-locale files were written into and every configured target locale found inside is read. |
| `cwd` | `string` | no | Directory the `files.pattern` and `workbook` are resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `dryRun` | `boolean` | no | Read and validate the handoff but write nothing. The returned RunSummary reports what would have been applied, which is the safe way to inspect a handoff before trusting it. Defaults to false. |
| `format` | `ExchangeFormat` | no | The handoff shape to read. Defaults to the shape the extension of ImportWorkbookInput.workbook names: `csv` for `.csv`, `tsv` for `.tsv`, `xliff2` for `.xlf` or `.xliff`, and `xlsx` for `.xlsx` or any other file. For a directory it is the format of the export manifest inside, else of the `<locale>` files inside; a directory holding two formats, or none, is refused. `xliff2` and `xliff12` both read either XLIFF version, which is taken from the file. |
| `reviewer` | `string` | no | Free text naming the reviewer, 1 to 64 characters with no control characters, recorded on each value an XLIFF handoff marks `reviewed` or `final` (1.2: `signed-off`, `final`, or `approved="yes"`). It is stored in the committed provenance file, so it is public. Other handoff formats carry no review state, so it is not used for them. |
| `onLockWait` | `LockWaitListener` | no | Called while waiting on another process's write lock, so a CLI can explain a stall instead of appearing to hang. Never called for a lock this process holds itself. |
| `lockAcquireTimeoutMs` | `number` | no | How long, in milliseconds, to wait for a locale's write lock before that locale fails with `LOCK_CONTENDED`. The wait happens before the locale file is written. Defaults to ten minutes. It does not bound the lock-file guard a locale takes to record its result once its target file is written: that wait always allows the ten-minute default, so a written file is not left unrecorded. Not used on a dry run, which takes no lock. |

**Devuelve:** [`RunSummary`](https://verbatra.kreitz-webdev.de/es/docs/sdk/run-summary.md)

**Lanza:** [`LOCK_TIMEOUT_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#lock_timeout_invalid), [`REVIEWER_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#reviewer_invalid), [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#unknown_format), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#source_invalid), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_path_collision), [`LOCK_FILE_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#lock_file_invalid), [`PROVENANCE_FILE_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#provenance_file_invalid)

**Ejemplo:** [El ciclo de ida y vuelta del libro](https://verbatra.kreitz-webdev.de/es/docs/programmatic-api.md#el-ciclo-de-ida-y-vuelta-del-libro)

Con `csv` o `tsv`, `workbook` es un solo
archivo de entrega o el directorio que contiene uno por locale, y el locale viene del nombre del
archivo. Un archivo que termina en `.csv` o `.tsv` se lee en ese formato si omites `format`, y un directorio en el formato de su manifiesto de exportación o de sus archivos de locale. Devuelve la misma forma `RunSummary` que `translate`
(con `needsReview` siempre vacío, ya que no interviene ningún proveedor). Una hoja de un locale que no
es un destino configurado hace fallar ese locale con `CONFIG_INVALID` como dato en el resumen, no como
excepción.

<AvailableFrom version="0.12.0" />

`onLockWait` y `lockAcquireTimeoutMs` se comportan exactamente como en `translate`.
`lockAcquireTimeoutMs` limita la espera por el bloqueo de escritura de un locale, que se toma antes
de escribir el archivo de ese locale, y un locale que sigue bloqueado después falla con
`LOCK_CONTENDED` en su propio resumen mientras los demás locales se importan. Registrar un archivo ya
escrito en el archivo de bloqueo siempre admite la espera predeterminada de diez minutos. Un dry run
no toma ningún bloqueo, así que ninguna de las dos opciones se le aplica.

<AvailableFrom version="0.12.0" />

`integrityRefusals` de cada locale nombra las filas que rechazó la puerta de integridad, con el motivo
y sus `details`, como cada rama ICU que no encaja con el idioma de destino. Una fila retenida porque su
origen cambió desde la exportación aparece solo en `integrityMismatches`. `exportWorkbook` marca como
`icu-arms` en sus columnas de revisión una traducción actual con ramas incorrectas.

<AvailableFrom version="0.12.0" />

Con `xliff2` o `xliff12`, que leen las dos versiones, y por defecto para una ruta `workbook` que termina en `.xlf` o `.xliff`, cada código en línea vuelve a su texto exacto antes de las mismas comprobaciones. Un destino igual al valor actual no cambia nada, una unidad cuyo id no nombra ninguna clave de origen aparece en `malformedRows`, y una unidad en estado `reviewed` o `final` (1.2: `signed-off`, `final` o `approved="yes"`) se registra como aprobada en el archivo de procedencia, con `reviewer` como nombre si se indica (validado como en `approveEntry`, `REVIEWER_INVALID`), y se informa con el aviso `HANDOFF_REVIEWS_RECORDED`.

## El par TMX [#el-par-tmx]

<AvailableFrom version="0.11.0" />

`importTmx` y `exportTmx` mueven la [memoria de traducción](https://verbatra.kreitz-webdev.de/es/docs/the-cache.md) hacia y desde TMX, el
formato de intercambio que producen y leen las plataformas de traducción más extendidas. Ninguna de
las dos construye un proveedor, lee una clave de API ni hace una petición de red: cada valor sale del
archivo o de la memoria que ya está en disco. No es el par del libro en otro formato. El par del libro
entrega a un traductor humano un corte por locale del delta pendiente; este par mueve la memoria
entera como un único archivo multilingüe entre herramientas.

### importTmx [#importtmx]

Lee un archivo TMX hacia la memoria del proyecto.

```ts title="Firma"
function importTmx(
  input: ImportTmxInput,
  deps?: ImportTmxDeps,
): Promise<ImportTmxResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `file` | `string` | yes | Path to the TMX file, resolved against `cwd`. |
| `cwd` | `string` | no | Directory the file and the memory are resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `dryRun` | `boolean` | no | Read and validate the file but write nothing. Defaults to false. |
| `overwrite` | `boolean` | no | Let an imported unit replace a translation the memory already holds for the same source and locale. Off by default, so the project's own memory wins a collision. |
| `locales` | `readonly string[]` | no | Subset of configured target locales to import. Defaults to all of them. |

**Devuelve:** `ImportTmxResult`

**Lanza:** [`UNKNOWN_FORMAT`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#unknown_format), [`CONFIG_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#config_invalid), [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#unknown_locale), [`SOURCE_UNREADABLE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#source_unreadable), [`SOURCE_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#source_invalid), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_path_collision), [`MEMORY_UNWRITABLE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#memory_unwritable)

**Ejemplo:** [El ciclo de ida y vuelta de TMX](https://verbatra.kreitz-webdev.de/es/docs/programmatic-api.md#el-ciclo-de-ida-y-vuelta-de-tmx)

Nada del archivo se da por bueno. El XML se analiza con el endurecimiento del paquete de
intercambio, de modo que una declaración de entidad, un subconjunto DTD interno, un archivo
demasiado grande o uno mal formado se rechaza con un error estructurado `SOURCE_INVALID` en lugar de
analizarse. Cuando el problema tiene un lugar en el archivo, el mensaje indica la línea, la columna
y, dentro de una unidad de traducción, su ordinal contando desde 1, y `tmxErrorLocation(error)`
devuelve el mismo lugar como `TmxErrorLocation`, o `undefined` para cualquier otro error, así que
nunca tienes que hacer cast del error ni de su `cause`. Una etiqueta de idioma se resuelve a un
locale configurado por una regla explícita: coincidencia exacta tras pasar a minúsculas y convertir
guiones bajos en guiones; si no, el locale configurado más largo que sea prefijo de subetiquetas de
la etiqueta (búsqueda de RFC 4647), o en su defecto un locale configurado que amplía la etiqueta
solo con subetiquetas de región o de variante, nunca con una escritura, de modo que dos etiquetas
con subetiquetas de escritura o de región distintas (`sr-Latn` y `sr-Cyrl`, `de-AT` y `de-CH`) nunca coinciden; y una
etiqueta solo se informa como ambigua cuando los locales a los que podría llegar no están en una
misma cadena de prefijos. Los segmentos de una unidad que resuelven al mismo locale, incluido el de
origen, nunca dejan ganar al último: una etiqueta exacta supera a una coincidencia por prefijo, y
dos segmentos del mismo rango con valores distintos no guardan nada para ese locale y se cuentan
como `conflicting` (en el locale de origen, la unidad se rechaza y se cuenta en
`conflictingSourceUnits`). Cada traducción candidata pasa después por la misma puerta de placeholders,
marcado en línea, ICU, degeneración y vacío que ya afrontan la salida del proveedor y una fila de libro rellenada,
y se comprueba cuando el registro entra en la memoria, no se deja para la ejecución que luego lo lee.

Cuando una unidad importada contradice una traducción que la memoria ya tiene, gana la memoria salvo
que se pase `overwrite`. Las unidades se guardan bajo la huella de configuración actual, la misma
clave que escribe una ejecución real, así que dejan de coincidir cuando cambian el proveedor, el
modelo, el tono, los términos del glosario que verbatra enviaría o el `localeMap` del proveedor. Importar el mismo archivo dos veces no cambia nada la segunda vez.

Ante datos dañados devuelve un informe en lugar de lanzar: cuántas unidades se leyeron, una cuenta
por locale de `added`, `unchanged`, `overwritten`, `kept`, `duplicates`, `conflicting` y `rejected`
por motivo, más las unidades omitidas, sin segmento de origen, que perdieron marcado en línea o cuyo
texto `sub` se dejó fuera (`subflowDroppedUnits`), y las etiquetas de idioma que no coincidieron o
coincidieron de forma ambigua. `memoryWritable` es `false` cuando el archivo de memoria lo escribió
un verbatra más nuevo, en cuyo caso se deja intacto. Los recuentos por locale se siguen informando
entonces, como en una ejecución de prueba, así que `added` y `overwritten` describen lo que habría
entrado; con `memoryWritable` en `false`, no entró nada.

<AvailableFrom version="0.12.0" />

Cada locale lista además sus `refusals`, un `TmxUnitRefusal` por cada unidad contada bajo un motivo
de la puerta: `{ unit, reason, details? }`, donde `unit` es la posición de la unidad en el archivo,
empezando en 1, y `details` nombra lo que falla, como cada rama ICU que no encaja con el idioma de
destino.

### tmxErrorLocation [#tmxerrorlocation]

Lee, a partir de lo que lanzó `importTmx`, dónde falló un archivo TMX rechazado. Devuelve una
`TmxErrorLocation` (`{ line, column, unit? }`, todo contando desde 1) para un rechazo
`SOURCE_INVALID` que tiene un lugar en el archivo, y `undefined` para cualquier otro error, incluido
un archivo que falta o es demasiado grande, así que nunca tienes que hacer cast del error ni de su
`cause`.

```ts title="Firma"
function tmxErrorLocation(
  error: unknown,
): TmxErrorLocation | undefined;
```

**Devuelve:** `TmxErrorLocation | undefined`

```ts title="Ejemplo"
import { importTmx, tmxErrorLocation, type VerbatraConfig } from "@verbatra/sdk";

declare const config: VerbatraConfig;

try {
  await importTmx({ config, file: "legacy.tmx" });
} catch (error) {
  const at = tmxErrorLocation(error);
  if (at !== undefined) console.error(`line ${at.line}, column ${at.column}`);
}
```

### exportTmx [#exporttmx]

Escribe la memoria como TMX 1.4b. `out` es por defecto `DEFAULT_TMX_PATH` (`verbatra-memory.tmx`),
exportado como constante. Antes de leer la memoria, `TMX_OUTPUT_CONFLICT` rechaza un `out` que no
nombra ningún archivo (también uno que termina en un separador de ruta), que queda fuera de `cwd` o
en el propio `cwd`, o que nombra un archivo de locale configurado, el archivo de bloqueo, la caché
de memoria de traducción, un archivo que verbatra busca para su configuración, el archivo
`configPath` o el archivo `glossaryPath`, sin distinguir mayúsculas de minúsculas y, cuando
`deps.fs` implementa `realpath` como el valor por defecto, otra vez tras resolver los enlaces
simbólicos. Una escritura que falla, porque el directorio no es escribible, ya hay un directorio en
esa ruta o el disco está lleno, lanza `TMX_UNWRITABLE` con el archivo y el código del sistema de
archivos en el mensaje. Solo se escriben las entradas bajo la huella de configuración actual, que es
el mismo conjunto que reutilizaría una ejecución. Las etiquetas de idioma se escriben en forma BCP
47 (`en_US` pasa a `en-US`), lo que no cambia cómo se indexa la memoria. Una memoria vacía produce
un archivo válido y vacío, no un error.

```ts title="Firma"
function exportTmx(
  input: ExportTmxInput,
  deps?: ExportTmxDeps,
): Promise<ExportTmxResult>;
```

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `VerbatraConfig` | yes | The resolved project config, normally from loadConfig. |
| `out` | `string` | no | Where to write the file. Defaults to DEFAULT_TMX_PATH, resolved against `cwd`. Refused with `TMX_OUTPUT_CONFLICT`, before anything is read or written, when it names no file, resolves outside `cwd` or to `cwd` itself, or names a configured locale file, the lock file, the translation-memory cache, a file verbatra searches for its configuration, the ExportTmxInput.configPath file, or the ExportTmxInput.glossaryPath file. Names are compared case-insensitively, and, when the file-system port implements `realpath`, again after symbolic links are resolved, so a link cannot carry the file anywhere a plain path could not. |
| `configPath` | `string` | no | The configuration file `config` was loaded from, absolute or relative to `cwd`. It is refused as the output path even when its name is not one verbatra searches for. |
| `glossaryPath` | `string` | no | The glossary file the config names, absolute or relative to `cwd`, normally the `path` of a file-backed LoadedConfig.glossary. It is refused as the output path. |
| `cwd` | `string` | no | Directory the output path and the memory are resolved against. Defaults to the project root of the config object loadConfig returned, else the process working directory; a copied or rebuilt config loses that root, so pass `cwd` from resolveProjectRoot. |
| `locales` | `readonly string[]` | no | Subset of configured target locales to export. Defaults to all of them. |
| `toolVersion` | `string` | no | Value for the TMX header's `creationtoolversion`. Defaults to `unknown`. |

**Devuelve:** `ExportTmxResult`

**Lanza:** [`UNKNOWN_LOCALE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#unknown_locale), [`CONFIG_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#config_invalid), [`TMX_OUTPUT_CONFLICT`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#tmx_output_conflict), [`TMX_UNWRITABLE`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#tmx_unwritable), [`LOCALE_LAYOUT_INVALID`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_layout_invalid), [`LOCALE_PATH_COLLISION`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_path_collision)

**Ejemplo:** [El ciclo de ida y vuelta de TMX](https://verbatra.kreitz-webdev.de/es/docs/programmatic-api.md#el-ciclo-de-ida-y-vuelta-de-tmx)

Devuelve `{ path, units, locales, withoutSource, illegalCharactersRemoved, provenanceMarkers }`; `withoutSource` cuenta las entradas dejadas fuera porque la memoria no tiene texto de origen para ellas, lo que solo ocurre con entradas arrastradas de una caché escrita antes de que la memoria guardase el texto de origen, e `illegalCharactersRemoved` cuenta los caracteres que XML 1.0 no puede representar y que se eliminaron del texto de los segmentos.

<AvailableFrom version="0.12.0" />

Cada segmento de destino lleva `<prop type="x-origin">` (`machine`, `human`, `import` o `unknown`,
el tipo `TmxOrigin`) y uno `machine` lleva además `<prop type="x-review">` (`approved`, `unreviewed`
o `rejected`, el tipo `TmxReview`), derivados de cada clave cuya entrada de bloqueo nombra el origen
del segmento y cuyo registro describe exactamente su texto. `provenanceMarkers` vale `"unavailable"`
cuando no se pudo leer el archivo de procedencia o el archivo de bloqueo, y en ese caso ningún
segmento lleva una propiedad.
