@inlang/sdk 2.4.1 → 2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,16 +1,242 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
# Inlang file format SDK
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@inlang/sdk) [](https://discord.gg/ecsc6bFtZw)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<img src="https://cdn.jsdelivr.net/gh/opral/monorepo/inlang/packages/sdk/assets/open-file.svg" alt="Inlang SDK opens .inlang files">
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
## Outline
|
|
11
|
+
|
|
12
|
+
- [Introduction](#introduction)
|
|
13
|
+
- [Getting Started](#getting-started)
|
|
14
|
+
- [Plugins](#plugins)
|
|
15
|
+
- [API reference](#api-reference)
|
|
16
|
+
- [Listing on inlang.com](#listing-on-inlangcom)
|
|
17
|
+
|
|
18
|
+
## Introduction
|
|
19
|
+
|
|
20
|
+
The inlang SDK is the official specification and parser for `.inlang` files.
|
|
21
|
+
|
|
22
|
+
`.inlang` files are designed to become the open standard for i18n and enable interoperability between i18n solutions. Such solutions involve apps like [Fink](https://inlang.com/m/tdozzpar/app-inlang-finkLocalizationEditor), libraries like [Paraglide JS](https://inlang.com/m/gerre34r/library-inlang-paraglideJs), or plugins that extend inlang.
|
|
23
|
+
|
|
24
|
+
### Core Features
|
|
25
|
+
|
|
26
|
+
- 📁 **File-based**: Interoperability without cloud integrations or lock-in.
|
|
27
|
+
- 🖊️ **CRUD API**: Query messages with SQL.
|
|
28
|
+
- 🧩 **Plugin System**: Extend the capabilities with plugins.
|
|
29
|
+
- 📦 **Import/Export**: Import and export messages in different file formats.
|
|
30
|
+
- [<img src="https://raw.githubusercontent.com/opral/monorepo/refs/heads/main/lix/assets/lix-icon.svg" width="20" height="12" alt="Lix Icon">**Change control**](https://lix.opral.com/): Collaboration, change proposals, reviews, and automation.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Getting Started
|
|
35
|
+
|
|
36
|
+
> [!Note]
|
|
37
|
+
> Inlang files can be unpacked and [stored as directories](#unpacked-inlang-files-directories). The long-term goal is to have portable `.inlang` files. Hence, the documentation refers to files instead of directories.
|
|
38
|
+
|
|
39
|
+
### Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @inlang/sdk
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Loading an inlang file
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { loadProjectInMemory, newProject } from "@inlang/sdk";
|
|
49
|
+
|
|
50
|
+
const project = await loadProjectInMemory({
|
|
51
|
+
blob: await newProject()
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// query the project
|
|
55
|
+
project.*
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Next steps
|
|
59
|
+
|
|
60
|
+
Go to the [API reference](#api-reference) to learn how to query messages, changes, and save the project.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## Plugins
|
|
64
|
+
|
|
65
|
+
The inlang SDK supports plugins to extend its functionality.
|
|
66
|
+
|
|
67
|
+
Plugins can be used to import/export messages in different formats, add custom validation rules, and implement specialized workflows.
|
|
68
|
+
|
|
69
|
+
### Available Plugins
|
|
70
|
+
|
|
71
|
+
Find available plugins on https://inlang.com/c/plugins.
|
|
72
|
+
|
|
73
|
+
### Creating a Plugin
|
|
74
|
+
|
|
75
|
+
#### Getting started
|
|
76
|
+
|
|
77
|
+
Implement the `InlangPlugin` type.
|
|
78
|
+
|
|
79
|
+
Examples can be found [here](https://github.com/opral/monorepo/tree/main/inlang/packages/plugins). Particulary the [message format plugin](https://github.com/opral/monorepo/tree/main/inlang/packages/plugins/inlang-message-format) is a good starting point.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const myPlugin: InlangPlugin = {
|
|
83
|
+
key: "my-plugin",
|
|
84
|
+
importFiles: () => {
|
|
85
|
+
// Import files logic
|
|
86
|
+
},
|
|
87
|
+
exportFiles: () => {
|
|
88
|
+
// Export files logic
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Deploying a plugin
|
|
94
|
+
|
|
95
|
+
> [!NOTE]
|
|
96
|
+
> Why is a CDN requires instead of using npm to use plugins?
|
|
97
|
+
>
|
|
98
|
+
> 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.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npx @inlang/cli plugin build --entry ./src/plugin.js
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
We 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.
|
|
105
|
+
|
|
106
|
+
```diff
|
|
107
|
+
https://cdn.jsdelivr.net/npm/my-plugin@1/dist/index.js
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## API reference
|
|
111
|
+
|
|
112
|
+
### Creating a new project
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { newProject } from "@inlang/sdk";
|
|
116
|
+
|
|
117
|
+
// Create a new project
|
|
118
|
+
const file = await newProject();
|
|
119
|
+
|
|
120
|
+
// write the file anywhere you want
|
|
121
|
+
await fs.writeFile("./project.inlang", file);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Loading a project
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { loadProjectInMemory } from "@inlang/sdk";
|
|
128
|
+
|
|
129
|
+
const file = await fs.readFile("./project.inlang");
|
|
130
|
+
|
|
131
|
+
// Load a project from a directory
|
|
132
|
+
const project = await loadProjectInMemory({
|
|
133
|
+
blob: file
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Querying a project
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Accessing settings and plugins
|
|
141
|
+
const settings = await project.settings.get();
|
|
142
|
+
const plugins = await project.plugins.get();
|
|
143
|
+
|
|
144
|
+
// Querying messages
|
|
145
|
+
const messages = await project.db
|
|
146
|
+
.selectFrom("message")
|
|
147
|
+
.selectAll()
|
|
148
|
+
.execute();
|
|
149
|
+
|
|
150
|
+
console.log(messages);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Querying changes
|
|
154
|
+
|
|
155
|
+
> [!NOTE]
|
|
156
|
+
> 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-sdk).
|
|
157
|
+
|
|
158
|
+
The inlang file format uses lix for change control. The lix APIs are exposed via `project.lix.*`. Visit the [lix documentation](https://lix.opral.com/) for more information on how to query changes.
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const changes = await project.lix.db
|
|
162
|
+
.selectFrom("change")
|
|
163
|
+
.selectAll()
|
|
164
|
+
.execute();
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Saving a project
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const newFile = await project.toBlob();
|
|
171
|
+
|
|
172
|
+
await fs.writeFile("./project.inlang", newFile);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Importing and exporting translation files
|
|
176
|
+
|
|
177
|
+
The 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.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const file = await fs.readFile("./en.json");
|
|
181
|
+
|
|
182
|
+
// Import files
|
|
183
|
+
await project.importFiles({
|
|
184
|
+
pluginKey: "plugin.inlang.messageFormat",
|
|
185
|
+
files: [
|
|
186
|
+
{ locale: "en", content: file },
|
|
187
|
+
],
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Export files
|
|
191
|
+
const files = await project.exportFiles({
|
|
192
|
+
pluginKey: "plugin.inlang.messageFormat"
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
await fs.writeFile("./en.json", files[0].content);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Installing plugins
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const settings = await project.settings.get();
|
|
202
|
+
|
|
203
|
+
settings.modules.push(
|
|
204
|
+
"https://cdn.jsdelivr.net/npm/@inlang/plugin-i18next@latest/dist/index.js"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
await project.settings.set(settings)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Unpacked inlang files (directories)
|
|
211
|
+
|
|
212
|
+
> [!NOTE]
|
|
213
|
+
> Unpacked inlang files are a workaround to store inlang files in git.
|
|
214
|
+
>
|
|
215
|
+
> Git can't handle binary files. **If you don't intend to store the inlang file in git, do not use unpacked inlang files.**
|
|
216
|
+
>
|
|
217
|
+
> Unpacked inlang files are not portable. They depent on plugins that and do not persist [lix change control](https://lix.opral.com/) data.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import {
|
|
221
|
+
loadProjectFromDirectory,
|
|
222
|
+
saveProjectToDirectory
|
|
223
|
+
} from "@inlang/sdk";
|
|
224
|
+
|
|
225
|
+
const project = await loadProjectFromDirectory({
|
|
226
|
+
"path": "./project.inlang"
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// modify the project
|
|
230
|
+
|
|
231
|
+
await saveProjectToDirectory({
|
|
232
|
+
"project": project,
|
|
233
|
+
"path": "./project.inlang"
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
## Listing on inlang.com
|
|
239
|
+
|
|
240
|
+
To list your app/plugin on inlang.com, please open a pull request to the [registry.json file](https://github.com/opral/monorepo/blob/main/inlang/packages/marketplace-registry/registry.json).
|
|
241
|
+
|
|
242
|
+
Make 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/monorepo/blob/main/inlang/packages/fink/marketplace-manifest.json)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const ENV_VARIABLES = {
|
|
2
2
|
PUBLIC_POSTHOG_TOKEN: "phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz",
|
|
3
3
|
PUBLIC_INLANG_SDK_SENTRY_DSN: "https://c3d92d5d011122e525e9f9b368e0905d@o4504345873285120.ingest.us.sentry.io/4507903389335553",
|
|
4
|
-
SDK_VERSION: "2.4.
|
|
4
|
+
SDK_VERSION: "2.4.3",
|
|
5
5
|
};
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"/","sources":["services/env-variables/index.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,oBAAoB,EAAE,iDAAiD;IACxE,4BAA4B,EAAE,iGAAiG;IAC/H,WAAW,EAAE,OAAO;CACpB,CAAA","sourcesContent":["\nexport const ENV_VARIABLES = {\n PUBLIC_POSTHOG_TOKEN: \"phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz\",\n\tPUBLIC_INLANG_SDK_SENTRY_DSN: \"https://c3d92d5d011122e525e9f9b368e0905d@o4504345873285120.ingest.us.sentry.io/4507903389335553\",\n\tSDK_VERSION: \"2.4.
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"/","sources":["services/env-variables/index.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,oBAAoB,EAAE,iDAAiD;IACxE,4BAA4B,EAAE,iGAAiG;IAC/H,WAAW,EAAE,OAAO;CACpB,CAAA","sourcesContent":["\nexport const ENV_VARIABLES = {\n PUBLIC_POSTHOG_TOKEN: \"phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz\",\n\tPUBLIC_INLANG_SDK_SENTRY_DSN: \"https://c3d92d5d011122e525e9f9b368e0905d@o4504345873285120.ingest.us.sentry.io/4507903389335553\",\n\tSDK_VERSION: \"2.4.3\",\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inlang/sdk",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"@sinclair/typebox": "^0.31.17",
|
|
30
30
|
"kysely": "^0.27.4",
|
|
31
31
|
"uuid": "^10.0.0",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
32
|
+
"@lix-js/sdk": "0.4.3",
|
|
33
|
+
"sqlite-wasm-kysely": "0.3.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@eslint/js": "^9.12.0",
|