@inlang/paraglide-js 1.3.7 → 1.4.0

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
@@ -6,15 +6,15 @@
6
6
  <doc-feature title="Tiny Runtime" image="https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/source-code/paraglide/paraglide-js/assets/bundlesize-feature.png"></doc-feature>
7
7
  <doc-feature title="Fully Typesafe" image="https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/source-code/paraglide/paraglide-js/assets/typesafety-feature.png"></doc-feature>
8
8
  <doc-feature title="Only Ship Used Messages" image="https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/source-code/paraglide/paraglide-js/assets/unused-translations.png"></doc-feature>
9
- <doc-feature title="Sherlock VsCode Extension" image="https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/source-code/paraglide/paraglide-js/assets/sherlock-preview.png"></doc-feature>
9
+ <doc-feature title="Sherlock VS Code Extension" image="https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/source-code/paraglide/paraglide-js/assets/sherlock-preview.png"></doc-feature>
10
10
  </doc-features>
11
11
 
12
12
 
13
- With Paraglide's Treeshsakeable messages, each page only loads the messages it actually uses. Incremental loading like this would usually take forever to get right, with Paraglide you get it for free.
13
+ With Paraglide's treeshakeable messages, each page only loads the messages it actually uses. Incremental loading like this would usually take forever to get right, with Paraglide you get it for free.
14
14
 
15
15
  # Use it with your Favorite Framework
16
16
 
17
- Paraglide is framework agnostic, but it's even better if you pair it with a framework specific library. If you are using one of these frameworks you will want to follow the framework specific documentation instead. If you aren't, that's fine too! You can read on.
17
+ Paraglide is framework agnostic, but there are framework-specific libraries available. If there is one for your framework you will want to follow its documentation instead. If there isn't, read on.
18
18
 
19
19
  <doc-links>
20
20
  <doc-link title="Adapter for NextJS" icon="tabler:brand-nextjs" href="/m/osslbuzt/paraglide-next-i18n" description="Go to Library"></doc-link>
@@ -27,18 +27,18 @@ Paraglide is framework agnostic, but it's even better if you pair it with a fram
27
27
 
28
28
  # People Love It
29
29
 
30
- Here are a few comments we've received recently.
30
+ A few recent comments.
31
31
 
32
32
  <doc-comments>
33
33
  <doc-comment text="Just tried Paraglide JS from @inlangHQ. This is how i18n should be done! Totally new level of DX for both implementation and managing translations! Superb support for SvelteKit as well ⭐" author="Patrik Engborg" icon="mdi:twitter" data-source="https://twitter.com/patrikengborg/status/1747260930873053674"></doc-comment>
34
- <doc-comment text="I was messing with various i18n frameworks and tools in combination with Astro, and i must say that Paraglide was the smoothest experience. I have migrated my website from i18next and it was a breeze. SSG and SSR worked out of the box (which was the first one for me), and overall DX is great. Thanks for your work!" author="Dalibor Hon" icon="mdi:discord" data-source="https://discord.com/channels/897438559458430986/1096039983116202034/1220796380772307004"></doc-comment>
35
- <doc-comment text="The lib is great guys!" author="ktarmyshov" icon="mdi:github"></doc-comment>
34
+ <doc-comment text="I was messing with various i18n frameworks and tools in combination with Astro, and must say that Paraglide was the smoothest experience. I have migrated my website from i18next and it was a breeze. SSG and SSR worked out of the box (which was the first one for me), and overall DX is great. Thanks for your work!" author="Dalibor Hon" icon="mdi:discord" data-source="https://discord.com/channels/897438559458430986/1096039983116202034/1220796380772307004"></doc-comment>
35
+ <doc-comment text="Awesome library 🙂 Thanks so much! 1) The docs were simple and straight forward 2) Everything just worked.. no headaches" author="Dimitry" icon="mdi:discord" data-source="https://discord.com/channels/897438559458430986/1083724234142011392/1225658097016766574"></doc-comment>
36
36
  <doc-comment text="Thank you for that huge work you have done and still doing!" author="ZerdoX-x" icon="mdi:github"></doc-comment>
37
37
  </doc-comments>
38
38
 
39
39
  # Getting started
40
40
 
41
- To use Paraglide stanadlone without a framework, run the following command:
41
+ To use Paraglide standalone without a framework, run the following command:
42
42
 
43
43
  ```bash
44
44
  npx @inlang/paraglide-js@latest init
@@ -48,10 +48,10 @@ This will:
48
48
 
49
49
  - Install necessary dependencies
50
50
  - Generate a `messages/` folder where your translation files live
51
- - Add the Paraglide compiler to your `build` script
51
+ - Add the Paraglide compiler to your `build` script in `package.json`
52
52
  - Create necessary configuration files
53
53
 
54
- Running the paraglide compiler will generate a `src/paraglide` folder. This folder contains all the code that you need to use paraglide-js.
54
+ Running the Paraglide compiler will generate a `src/paraglide` folder. This folder contains all the code that you will use in your app.
55
55
 
56
56
  ## Adding and Editing Messages
57
57
 
@@ -67,11 +67,11 @@ Messages are stored in `messages/{lang}.json`. To add a message simply add a key
67
67
 
68
68
  Make sure to re-run the paraglide compiler after editing your messages.
69
69
 
70
- ```
71
- npx @inlang/paraglide-js compile --project ./project.inlang
70
+ ```bash
71
+ npx @inlang/paraglide-js compile --project ./project.inlang --outdir ./src/paraglide
72
72
  ```
73
73
 
74
- If you are using Vite, you can instead use the [paraglide vite-plugin](https://github.com/opral/monorepo/tree/main/inlang/source-code/paraglide/paraglide-js-adapter-vite) to do this automatically.
74
+ If you are using Bundler, you can use one of the [Bundler Plugins](#usage-with-a-bundler) to recompile automatically.
75
75
 
76
76
  ## Using Messages in Code
77
77
 
@@ -100,23 +100,6 @@ const season = {
100
100
  const msg = season["spring"]() // Hello spring!
101
101
  ```
102
102
 
103
- ## Configuration
104
-
105
- You can configure the languages you intend to support
106
-
107
- ### Languages
108
-
109
- You can declare which languages you support in `./project.inlang/settings.json`.
110
-
111
- ```json
112
- // project.inlang/settings.json
113
- {
114
- "languageTags": ["en", "de"]
115
- }
116
- ```
117
-
118
- Then create another `messages/{lang}.json` file and get translating!
119
-
120
103
  ## Setting the language
121
104
 
122
105
  You can set the [language tag](https://www.inlang.com/m/8y8sxj09/library-inlang-languageTag) by calling `setLanguageTag()`. Any subsequent calls to either `languageTag()` or a message function will use the new language tag.
@@ -134,13 +117,13 @@ m.hello() // Hello world!
134
117
 
135
118
  The [language tag](https://www.inlang.com/m/8y8sxj09/library-inlang-languageTag) is global, so you need to be careful with it on the server to make sure multiple requests don't interfere with each other.
136
119
 
137
- You will need to call `setLanguageTag` on both the server and the client, since they run in separate processes.
120
+ You will need to call `setLanguageTag` on both the server and the client since they run in separate processes.
138
121
 
139
122
  ## Reacting to language changes
140
123
 
141
124
  Messages aren't reactive, so you will need to trigger a re-render when the language changes. You can register a callback using `onSetLanguageTag()`. It is called whenever the [language tag](https://www.inlang.com/m/8y8sxj09/library-inlang-languageTag) changes.
142
125
 
143
- If you are using an adapter this is likely done for you.
126
+ If you are using a [framework-specific library](#use-it-with-your-favorite-framework) this is done for you.
144
127
 
145
128
  ```js
146
129
  import { setLanguageTag, onSetLanguageTag } from "./paraglide/runtime.js"
@@ -154,10 +137,10 @@ setLanguageTag("de") // The language changed to de
154
137
  setLanguageTag("en") // The language changed to en
155
138
  ```
156
139
 
157
- There are a few things to know about `onSetLanguageTag()`:
140
+ A few things to know about `onSetLanguageTag()`:
158
141
 
159
142
  - You can only register one listener. If you register a second listener it will throw an error.
160
- - `setLanguageTag` shouldn't be used on the server.
143
+ - `onSetLanguageTag` shouldn't be used on the server.
161
144
 
162
145
  ## Getting a message in a specific language
163
146
 
@@ -178,9 +161,9 @@ const msg = m.hello({ name: "Samuel" }, { languageTag: "de" }) // Hallo Samuel!
178
161
  ## Lazy-Loading
179
162
 
180
163
  Paraglide consciously discourages lazy-loading translations since it seriously hurts
181
- your web-vitals. Learn more about why lazy-loading is bad & what to do instead in [this blog post](https://inlang.com/g/mqlyfa7l/guide-lorissigrist-dontlazyload).
164
+ your Web Vitals. Learn more about why lazy-loading is bad & what to do instead in [our blog post on lazy-loading](https://inlang.com/g/mqlyfa7l/guide-lorissigrist-dontlazyload).
182
165
 
183
- If you _really_ want to do it anway, you can lazily import the language-specific message files. Be careful with this.
166
+ If you want to do it anyway, lazily import the language-specific message files. Be careful with this.
184
167
 
185
168
  ```ts
186
169
  const lazyGerman = await import("./paraglide/messages/de.js")
@@ -189,7 +172,7 @@ lazyGerman.hello() // Hallo Welt
189
172
 
190
173
  ## Usage with a Bundler
191
174
 
192
- If you are using a bundler you should use the corresponding plugin. The plugin will keep your message-functions up-to-date by compiling whenever your messages change and before build.
175
+ If you are using a bundler you should use the corresponding plugin. The plugin will keep your Message Functions up-to-date by compiling whenever your messages change and before building your app.
193
176
 
194
177
  <doc-links>
195
178
  <doc-link title="Vite Plugin" icon="tabler:brand-vite" href="https://github.com/opral/monorepo/tree/main/inlang/source-code/paraglide/paraglide-js-adapter-vite" description="Go to Github"></doc-link>
@@ -197,9 +180,44 @@ If you are using a bundler you should use the corresponding plugin. The plugin w
197
180
  <doc-link title="Webpack Plugin" icon="mdi:webpack" href="https://github.com/opral/monorepo/tree/main/inlang/source-code/paraglide/paraglide-js-adapter-webpack" description="Go to Github"></doc-link>
198
181
  </doc-links>
199
182
 
183
+ ## Configuration
184
+
185
+ Most of the configuration is done in `./project.inlang/settings.json`, except for paraglide's output directory, which needs to be passed in when calling the compiler.
186
+
187
+ ### Languages
188
+
189
+ You can declare which languages you support in the `languageTags` array.
190
+
191
+ ```json
192
+ // project.inlang/settings.json
193
+ {
194
+ "languageTags": ["en", "de"]
195
+ }
196
+ ```
197
+
198
+ Create the corresponding `messages/{lang}.json` files and get translating!
199
+
200
+ ### Moving the Translation Files
201
+
202
+ If you want your language files to be in a different location you can change the `pathPattern` of the [Inlang-Message-Format plugin](https://inlang.com/m/reootnfj/plugin-inlang-messageFormat).
203
+
204
+ ```diff
205
+ // project.inlang/settings.json
206
+ "plugin.inlang.messageFormat": {
207
+ - "pathPattern": "./messages/{languageTag}.json"
208
+ + "pathPattern": "./i18n/{languageTag}.json"
209
+ },
210
+ ```
211
+
212
+ ### Lint Rules
213
+
214
+ If you're using the [Sherlock VS Code extension](https://inlang.com/m/r7kp499g/app-inlang-ideExtension) you might see warnings about certain messages. Perhaps they're duplicates, perhaps they're missing in one language.
215
+
216
+ You can configure which lint-rules are active in `./project.inlang/settings.json`. Simply add or remove them from the `modules` array.
217
+
200
218
  # Playground
201
219
 
202
- Find examples for how to use paraglide on codesandbox or in [our GitHub repository](https://github.com/opral/monorepo/tree/main/inlang/source-code/paraglide).
220
+ Find examples of how to use Paraglide on CodeSandbox or in [our GitHub repository](https://github.com/opral/monorepo/tree/main/inlang/source-code/paraglide).
203
221
 
204
222
  <doc-links>
205
223
  <doc-link title="NextJS + Paraglide JS" icon="lucide:codesandbox" href="https://stackblitz.com/~/LorisSigrist/paraglide-next-app-router-example" description="Play around with NextJS and Paraglide JS"></doc-link>
@@ -213,11 +231,11 @@ ParaglideJS leverages a compiler to generate vanilla JavaScript functions from y
213
231
 
214
232
  Message Functions are fully typed using JSDoc. They are exported individually from the `messages.js` file making them tree-shakable. They aren't reactive, they just return a string.
215
233
 
216
- This avoids many edge cases associated with reactivity, lazy-loading and namespacing that other i18n libraries have to work around.
234
+ This avoids many edge cases associated with reactivity, lazy-loading, and namespacing that other i18n libraries have to work around.
217
235
 
218
236
  In addition to the message functions, ParaglideJS also emits a runtime. The runtime is used to set the language tag. It contains less than 50 LOC (lines of code) and is less than 300 bytes minified & gzipped.
219
237
 
220
- ![paraglide JS architecture](https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/source-code/paraglide/paraglide-js/assets/architecture.svg)
238
+ ![Diagram of the Paraglide Compiler Architecture](https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/source-code/paraglide/paraglide-js/assets/architecture.svg)
221
239
 
222
240
  Paraglide consists of four main parts:
223
241
 
@@ -255,7 +273,7 @@ export const hello = (params) => `Hello ${params.name}!`
255
273
 
256
274
  ## Messages
257
275
 
258
- By convention we import the compiled funcitions with a wildcard import.
276
+ By convention, we import the compiled functions with a wildcard import.
259
277
 
260
278
  ```js
261
279
  import * as m from "../paraglide/messages.js"
@@ -265,12 +283,12 @@ Bundlers like Rollup, Webpack, or Turbopack tree-shake the messages that are not
265
283
 
266
284
  # Writing an Adapter
267
285
 
268
- An "Adapter" is a library that integrates with a framework's liefcycle and does two things:
286
+ An "Adapter" is a library that integrates with a framework's lifecycle and does two things:
269
287
 
270
288
  1. Calls `setLanguageTag()` at appropriate times to set the language
271
289
  2. Reacts to `onSetLanguageTag()`, usually by navigating or relading the page.
272
290
 
273
- This example adapts Paraglide to a fictitious fullstack framework.
291
+ This example adapts Paraglide to a fictitious full-stack framework.
274
292
 
275
293
  ```tsx
276
294
  import {
@@ -331,9 +349,9 @@ Of course, we're not done yet! We plan on adding the following features to Parag
331
349
 
332
350
  # Tooling
333
351
 
334
- Paraglide JS is part of the Inlang ecosystem and integrates nicely with all the other Inlang compatible tools.
352
+ Paraglide JS is part of the Inlang ecosystem and integrates nicely with all the other Inlang-compatible tools.
335
353
 
336
- As a developer, you will love the [Sherlock VsCode extension](https://inlang.com/m/r7kp499g/app-inlang-ideExtension).
354
+ As a developer, you will love the [Sherlock VS Code extension](https://inlang.com/m/r7kp499g/app-inlang-ideExtension).
337
355
 
338
356
  If you are working with translators or designers you will find these tools useful:
339
357
 
@@ -1,2 +1,3 @@
1
- import { Command } from "commander";
1
+ import { Command } from 'commander';
2
+
2
3
  export declare const compileCommand: Command;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * One step in a CLI chain.
3
+ * Defines which types the context needs to extend and how it extends the context
4
+ *
5
+ * Cli Steps can be chained to slowly build up the context over time
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const step1: CliStep<unknown, { foo: string }> = async (ctx) => {
10
+ * return {...ctx, foo: "hello" }
11
+ * }
12
+ *
13
+ * const step2: CliStep<{ foo: string }, { bar: number }> = async (ctx) => {
14
+ * return { ...ctx, bar: 42 }
15
+ * }
16
+ *
17
+ * const initial = { baz: "baz" } as const;
18
+ * const ctx1 = await step1(initial);
19
+ * const ctx2 = await step2(ctx1);
20
+ *
21
+ * ctx2 // Has type { foo: string, bar: number, baz: "baz" }
22
+ * ```
23
+ */
24
+ export type CliStep<In extends object, Out> = <Ctx extends In>(ctx: Ctx) => Promise<Ctx & Out>;
@@ -1,41 +1,70 @@
1
- import { Command } from "commander";
2
- import { type InlangProject } from "@inlang/sdk";
3
- import { Logger } from "../../../services/logger/index.js";
4
- import { type Repository } from "@lix-js/client";
5
- type Context = {
6
- logger: Logger;
7
- repo: Repository;
8
- };
1
+ import { CliStep } from './cli-utils.js';
2
+ import { Repository } from '@lix-js/client';
3
+ import { Logger } from '~/services/logger/index.js';
4
+ import { InlangProject } from '@inlang/sdk';
5
+ import { Command } from 'commander';
6
+
9
7
  export declare const initCommand: Command;
10
- export declare const initializeInlangProject: (ctx: Context) => Promise<{
8
+ export declare const initializeInlangProject: CliStep<{
9
+ repo: Repository;
10
+ logger: Logger;
11
+ }, {
11
12
  project: InlangProject;
12
13
  /** Relative path to the project */
13
14
  projectPath: string;
14
15
  }>;
15
- export declare const maybeAddVsCodeExtension: (args: {
16
- projectPath: string;
17
- }, ctx: Context) => Promise<void>;
18
- export declare const addParaglideJsToDevDependencies: (ctx: Context) => Promise<void>;
19
- export declare const findExistingInlangProjectPath: (ctx: Context) => Promise<string | undefined>;
20
- export declare const existingProjectFlow: (args: {
16
+ export declare const maybeAddVsCodeExtension: CliStep<{
17
+ repo: Repository;
18
+ logger: Logger;
19
+ project: InlangProject;
20
+ }, unknown>;
21
+ export declare const addParaglideJsToDevDependencies: CliStep<{
22
+ repo: Repository;
23
+ logger: Logger;
24
+ }, unknown>;
25
+ export declare const findExistingInlangProjectPath: (repo: Repository) => Promise<string | undefined>;
26
+ export declare const determineOutdir: CliStep<{
27
+ logger: Logger;
28
+ }, {
29
+ /** Relative path to the output directory */
30
+ outdir: string;
31
+ }>;
32
+ export declare const existingProjectFlow: (ctx: {
21
33
  existingProjectPath: string;
22
- }, ctx: Context) => Promise<InlangProject>;
23
- export declare const createNewProjectFlow: (ctx: Context) => Promise<InlangProject>;
24
- export declare const checkIfPackageJsonExists: (ctx: Context) => Promise<undefined>;
25
- export declare const checkIfUncommittedChanges: (ctx: Context) => Promise<void>;
26
- export declare const addCompileStepToPackageJSON: (args: {
34
+ repo: Repository;
35
+ logger: Logger;
36
+ }) => Promise<InlangProject>;
37
+ export declare const createNewProjectFlow: (ctx: {
38
+ repo: Repository;
39
+ logger: Logger;
40
+ }) => Promise<InlangProject>;
41
+ export declare const checkIfPackageJsonExists: CliStep<{
42
+ logger: Logger;
43
+ repo: Repository;
44
+ }, unknown>;
45
+ export declare const checkIfUncommittedChanges: CliStep<{
46
+ logger: Logger;
47
+ }, unknown>;
48
+ export declare const addCompileStepToPackageJSON: CliStep<{
49
+ repo: Repository;
50
+ logger: Logger;
27
51
  projectPath: string;
28
52
  outdir: string;
29
- }, ctx: Context) => Promise<undefined>;
53
+ }, unknown>;
30
54
  /**
31
55
  * Ensures that the moduleResolution compiler option is set to "bundler" or similar in the tsconfig.json.
32
56
  *
33
57
  * Otherwise, types defined in `package.exports` are not resolved by TypeScript. Leading to type
34
58
  * errors with Paraglide-JS.
35
59
  */
36
- export declare const maybeChangeTsConfigModuleResolution: (ctx: Context) => Promise<void>;
60
+ export declare const maybeChangeTsConfigModuleResolution: CliStep<{
61
+ repo: Repository;
62
+ logger: Logger;
63
+ }, unknown>;
37
64
  /**
38
65
  * Paraligde JS compiles to JS with JSDoc comments. TypeScript doesn't allow JS files by default.
39
66
  */
40
- export declare const maybeChangeTsConfigAllowJs: (ctx: Context) => Promise<void>;
41
- export {};
67
+ export declare const maybeChangeTsConfigAllowJs: CliStep<{
68
+ repo: Repository;
69
+ logger: Logger;
70
+ }, unknown>;
@@ -1,2 +1,3 @@
1
- import { Command } from "commander";
1
+ import { Command } from 'commander';
2
+
2
3
  export declare const cli: Command;
@@ -1,4 +1,5 @@
1
- import { ProjectSettings, type Message } from "@inlang/sdk";
1
+ import { ProjectSettings, Message } from '@inlang/sdk';
2
+
2
3
  /**
3
4
  * A compile function takes a list of messages and project settings and returns
4
5
  * a map of file names to file contents.
@@ -1,4 +1,5 @@
1
- import { LanguageTag, type Message } from "@inlang/sdk";
1
+ import { LanguageTag, Message } from '@inlang/sdk';
2
+
2
3
  type Resource = {
3
4
  index: string;
4
5
  [languageTag: string]: string;