PageSourceSearch

https://inlang.com/assets/README-DAfBYuyd.js

js inlang.com collected 2026-09-25 20:53:09 UTC 10,018 bytes, 290 lines download raw bytes

1const n=`# Inlang file format SDK
2
3[![NPM Downloads](https://img.shields.io/npm/dw/%40inlang%2Fsdk?logo=npm&logoColor=red&label=npm%20downloads)](https://www.npmjs.com/package/@inlang/sdk) [![Discord](https://img.shields.io/discord/897438559458430986?style=flat&logo=discord&labelColor=white)](https://discord.gg/gdMPPWy57R)
4
5
6<p align="center">
7  <img src="https://cdn.jsdelivr.net/gh/opral/inlang/packages/sdk/assets/open-file.svg" alt="Inlang SDK opens .inlang files">
8</p>
9
10## Outline
11
12- [Introduction](#introduction)
13- [Use the SDK when](#use-the-sdk-when)
14- [Getting Started](#getting-started)
15- [Plugins](#plugins)
16- [API reference](#api-reference)
17- [Listing on inlang.com](#listing-on-inlangcom)
18
19## Introduction
20
21The inlang SDK is the reference implementation for reading and writing \`.inlang\` project files.
22
23\`.inlang\` files are designed to become the open standard for localization data and make i18n tools work together. Build editors, CLIs, runtimes, agents, and plugins on the same shared project format instead of inventing another file structure.
24
25An \`.inlang\` project is canonically a portable snapshot backed by [Lix](https://lix.dev). It packages localization data and project files into one file that tools can share.
26
27For Git repositories, the packed file can be unpacked into a directory of plain files so changes can be reviewed alongside code. The packed file is the canonical format; the unpacked directory is the Git-friendly representation.
28
29\`.inlang\` is the canonical project format. Plugins import and export formats like JSON, ICU MessageFormat v1, i18next, and XLIFF for compatibility with existing translation files and runtimes. Version control via lix adds file-level history, merging, and change proposals to \`.inlang\` projects.
30
31Messages, variants, and locale data live in the \`.inlang\` database. External translation files such as \`messages/en.json\` are compatibility files outside \`project.inlang/\`, connected through plugins.
32
33### Core Features
34
35- 📁 **File-based**: A portable project file, no cloud integrations or lock-in.
36- 🖊️ **CRUD API**: Read, write, and query messages with SQL.
37- 🧩 **Plugin System**: Connect external translation files to the shared message structure.
38- 📦 **Import/Export**: Import and export messages in formats like JSON, XLIFF, and i18next.
39- [<img src="https://raw.githubusercontent.com/opral/inlang/refs/heads/main/lix/assets/lix-icon.svg" width="20" height="12" alt="Lix Icon">**Version control via lix**](https://lix.dev/): File-level history, merging, change proposals, reviews, and automation.
40
41### Core data model
42
43- **Bundle** — one translatable unit across locales
44- **Message** — locale-specific translation for a bundle
45- **Variant** — text pattern plus selector matches
46
47## Use the SDK when
48
49Use \`@inlang/sdk\` when you are building an editor, CLI, CI check, migration, report, plugin, runtime, or AI agent that needs to read or write localization data.
50
51Instead of inventing another i18n JSON schema, target the shared \`.inlang\` project model. Your tool can then work with the same source of truth as Fink, Sherlock, Parrot, the CLI, Paraglide, plugins, and other inlang-compatible workflows.
52
53| Layer | What it is |
54| --- | --- |
55| \`.inlang\` | Canonical project format and localization source of truth |
56| \`@inlang/sdk\` | Read/write API for editors, CLIs, CI checks, runtimes, plugins, and agents |
57| Plugins | Compatibility layer for JSON, ICU MessageFormat, i18next, XLIFF, and other file formats |
58| Lix | Versioning, history, review, change proposals, rollback, and merging |
59| Tools | Fink, Sherlock, Parrot, CLI, and Paraglide workflows that read/write \`.inlang\` |
60
61For coding agents:
62
63- Find an existing \`project.inlang\` file or \`project.inlang/\` directory before creating new locale files.
64- Load and update bundles, messages, variants, locales, settings, and metadata through \`@inlang/sdk\`.
65- Treat JSON, ICU, i18next, and XLIFF files as compatibility files connected through plugins.
66- Do not invent a custom \`locales/en.json\` schema when a \`.inlang\` project already exists.
67
68## Getting Started
69
70> [!Note]
71> Inlang projects are portable snapshots. They can be unpacked and [stored as directories](#unpacked-inlang-files-directories) when you want to review changes in Git. The packed file remains the canonical format.
72
73### Installation
74
75\`\`\`bash
76npm install @inlang/sdk
77\`\`\`
78
79### Loading an inlang file
80
81\`\`\`ts
82import { loadProjectInMemory, newProject } from "@inlang/sdk";
83
84const project = await loadProjectInMemory({
85  blob: await newProject()
86});
87
88// query the project
89project.*
90\`\`\`
91
92### Loading an unpacked project from Git
93
94\`\`\`ts
95import { loadProjectFromDirectory } from "@inlang/sdk";
96
97const project = await loadProjectFromDirectory({
98  path: "./project.inlang",
99});
100\`\`\`
101
102### Next steps
103
104Go to the [API reference](#api-reference) to learn how to query messages, changes, and save the project.
105
106
107## Plugins
108
109The inlang SDK supports plugins to extend its functionality. 
110
111Plugins can be used to import/export messages in different formats, add custom validation rules, and implement specialized workflows.
112
113### Available Plugins
114
115Find available plugins on https://inlang.com/c/plugins.
116
117### Creating a Plugin
118
119#### Getting started
120
121Implement the \`InlangPlugin\` type. 
122
123Examples can be found [here](https://github.com/opral/inlang/tree/main/packages/plugins). Particulary the [message format plugin](https://github.com/opral/inlang/tree/main/packages/plugins/inlang-message-format) is a good starting point.
124
125\`\`\`typescript
126const myPlugin: InlangPlugin = {
127  key: "my-plugin",
128  importFiles: () => {
129    // Import files logic
130  },
131  exportFiles: () => {
132    // Export files logic
133  },
134};
135\`\`\`
136
137#### Deploying a plugin 
138
139> [!NOTE]  
140> Why is a CDN requires instead of using npm to use plugins?
141>
142> Non-JS projects (Android, iOS, etc.) wouldn't be able to use inlang, and browser-based apps like [Fink](https://inlang.com/m/tdozzpar/app-inlang-finkLocalizationEditor) couldn't load plugins. 
143
144\`\`\`bash
145npx @inlang/cli plugin build --entry ./src/plugin.js 
146\`\`\`
147
148We recommend uploading the plugin to NPM which makes it automatically available on [JSDelivr](https://www.jsdelivr.com/) and enables users to pin the version of your plugin. 
149
150\`\`\`diff
151https://cdn.jsdelivr.net/npm/my-plugin@1/dist/index.js
152\`\`\`
153
154## API reference
155
156### Creating a new project
157
158\`\`\`typescript
159import { newProject } from "@inlang/sdk";
160
161// Create a new project
162const file = await newProject();
163
164// write the file anywhere you want
165await fs.writeFile("./project.inlang", file);
166\`\`\`
167
168### Loading a project
169
170\`\`\`typescript
171import { loadProjectInMemory } from "@inlang/sdk";
172
173const file = await fs.readFile("./project.inlang");
174
175// Load a project from a directory
176const project = await loadProjectInMemory({
177  blob: file
178});
179\`\`\`
180
181### Querying a project
182
183\`\`\`typescript
184// Accessing settings and plugins
185const settings = await project.settings.get();
186const plugins = await project.plugins.get();
187
188// Querying messages
189const messages = await project.db
190  .selectFrom("message")
191  .selectAll()
192  .execute();
193
194console.log(messages);
195\`\`\`
196
197### Querying changes
198
199> [!NOTE]  
200> The inlang plugin for lix is work in progress. If you stumble on issues, please open an issue on the [GitHub](https://github.com/opral/inlang).
201
202The inlang file format uses version control via lix. \`project.lix\` is the underlying Lix instance. Visit the [lix documentation](https://lix.dev/) for more information on how to query changes.
203
204\`\`\`typescript
205const result = await project.lix.execute(\`
206  SELECT created_at, schema_key, entity_pk, snapshot_content
207  FROM lix_change
208  ORDER BY created_at DESC
209\`);
210
211const changes = result.rows.map((row) => row.toObject());
212\`\`\`
213
214### Saving a project
215
216\`\`\`typescript
217const newFile = await project.toBlob();
218
219await fs.writeFile("./project.inlang", newFile);
220\`\`\`
221
222### Importing and exporting translation files
223
224The import and export of messages depends on the installed plugins. The following example shows how to import and export messages using a plugin that supports JSON files.
225
226\`\`\`typescript
227const file = await fs.readFile("./en.json");
228
229// Import files
230await project.importFiles({
231  pluginKey: "plugin.inlang.messageFormat",
232  files: [
233    { locale: "en", content: file },
234  ],
235});
236
237// Export files
238const files = await project.exportFiles({
239  pluginKey: "plugin.inlang.messageFormat"
240});
241
242await fs.writeFile("./en.json", files[0].content);
243\`\`\`
244
245### Installing plugins
246
247\`\`\`typescript
248const settings = await project.settings.get();
249
250settings.modules.push(
251  "https://cdn.jsdelivr.net/npm/@inlang/plugin-i18next@latest/dist/index.js"
252)
253
254await project.settings.set(settings)
255\`\`\`
256
257### Unpacked inlang files (directories)
258
259> [!NOTE]  
260> Unpacked inlang files are the Git-friendly representation of packed \`.inlang\` files.
261>
262> Git can store packed snapshots, but plain-file review and merge workflows work better with the unpacked directory. **If you don't intend to store the inlang file in git, use the packed file.**
263> 
264> Unpacked inlang files are not portable. They depend on plugins and do not persist [version control via lix](https://lix.dev/) data.
265
266\`\`\`typescript
267import { 
268    loadProjectFromDirectory, 
269    saveProjectToDirectory 
270} from "@inlang/sdk";
271
272const project = await loadProjectFromDirectory({
273    "path": "./project.inlang"
274});
275
276// modify the project
277
278await saveProjectToDirectory({
279    "project": project,
280    "path": "./project.inlang"
281});
282\`\`\`
283
284
285## Listing on inlang.com
286
287To list your app/plugin on inlang.com, please open a pull request to the [registry.json file](https://github.com/opral/inlang/blob/main/packages/marketplace-registry/registry.json). 
288
289Make sure that the link you are contributing points to a \`marketplace-manifest.json\` file. An example of can be found [here](https://github.com/opral/inlang/blob/main/packages/fink/marketplace-manifest.json)
290`;export{n as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.