Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/lucky-moons-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'saykit': minor
'@saykit/config': minor
'@saykit/react': minor
'babel-plugin-saykit': minor
'unplugin-saykit': minor
---

Compile catalogues to data modules with `saykit compile`, and drop the runtime message parser
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ node_modules/
.turbo/
.coverage/
dist/
RELEASE_NOTES.md
RELEASE_NOTES.md
# Locale modules the saykit CLI compiles from the catalogues beside them.
# Their declarations are committed, so `tsc` passes before anything is generated.
examples/**/locales/*.js
examples/**/_locales/**/*.js
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ This is a pnpm monorepo. The published packages live in [`packages/*`](./package

| Package | Description |
| --------------------------------------------------- | -------------------------------------------------------------------- |
| [`saykit`](./packages/integration) | Core runtime: catalogues, views, macros, and ICU formatting |
| [`saykit`](./packages/integration) | Core runtime: catalogues, views, macros, and `Intl` helpers |
| [`@saykit/config`](./packages/config) | Config schema (`defineConfig`) and the `saykit` CLI |
| [`@saykit/react`](./packages/integration-react) | React integration: `<Say>`, `SayProvider`, server helpers |
| [`@saykit/carbon`](./packages/integration-carbon) | Carbon Discord-bot integration |
Expand Down
29 changes: 13 additions & 16 deletions examples/babel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
SayKit compiled by **Babel and nothing else**: no bundler, no dev server, no loader.
`pnpm build`, then `node dist/main.js`.

This exists to pin down the `catalogues: 'inline'` default: `babel-plugin-saykit` on its
own has to rewrite the macros _and_ resolve the catalogue imports, with no other tool
involved. Every other example runs the plugin alongside a bundler integration, so this is
the only one that would notice if that stopped being true.
This exists to pin down what `babel-plugin-saykit` does on its own: rewrite the macros,
and nothing else. Catalogues are compiled to `.js` modules by `saykit compile`, which Node
imports directly. Every other example runs the plugin alongside a bundler, so this is the
only one that would notice if the plugin started needing one.

## Run

Expand All @@ -31,18 +31,15 @@ English source string, merged in at compile time rather than looked up at runtim

## What to look at

| Thing | Where |
| ----------------------------------------------------------------- | ----------------- |
| `plugins: ['saykit']`, no options: the inlining default | `babel.config.js` |
| `import en from './locales/en.po'`, gone by the time Node sees it | `src/main.ts` |
| The compiled record, one object literal per locale | `dist/main.js` |
| Thing | Where |
| ------------------------------------------------------ | ------------------- |
| `plugins: ['saykit']`, no options and nothing else | `babel.config.js` |
| `import en from './locales/en.js'`, an ordinary import | `src/main.ts` |
| One readable function per message | `src/locales/fr.js` |

Open `dist/main.js` after a build: there is no `.po` file, no PO parser and no SayKit
extractor in the output, just `const en = { … }` and `say.call()` invocations.
Open `dist/main.js` after a build: no `.po` file, no PO parser, no message parser and no
SayKit extractor, just `say.call()` invocations against the imported locale modules.

## Hot reload

There is none, by design. The record lands inside `dist/main.js`, whose own bytes only
change when you rebuild, which is exactly why a dev server wants `catalogues: 'module'`
and a bundler integration instead. See the
Open `src/locales/fr.js` to see what those modules hold: one plain function per message,
with the locale and every number and date format already resolved. See the
[Babel integration docs](../../website/content/integrations/babel.mdx).
8 changes: 6 additions & 2 deletions examples/babel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
"scripts": {
"check": "tsc --noEmit",
"extract": "saykit extract",
"build": "babel src --extensions .ts --out-dir dist --ignore \"src/**/*.d.po.ts\"",
"start": "pnpm build && node dist/main.js"
"build": "babel src --extensions .ts,.js --out-dir dist --ignore \"src/**/*.d.ts\"",
"start": "pnpm build && node dist/main.js",
"compile": "saykit compile",
"prebuild": "saykit compile",
"precheck": "saykit compile",
"prestart": "saykit compile"
},
"dependencies": {
"saykit": "workspace:^"
Expand Down
2 changes: 0 additions & 2 deletions examples/babel/src/locales/en.d.po.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/babel/src/locales/en.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/babel/src/locales/fr.d.po.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/babel/src/locales/fr.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
4 changes: 2 additions & 2 deletions examples/babel/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createCatalogue } from 'saykit';
import en from './locales/en.po';
import fr from './locales/fr.po';
import en from './locales/en.js';
import fr from './locales/fr.js';

const catalogue = createCatalogue({ en, fr });

Expand Down
2 changes: 0 additions & 2 deletions examples/browser-extension/_locales/de/messages.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/browser-extension/_locales/de/messages.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/browser-extension/_locales/en/messages.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/browser-extension/_locales/en/messages.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/browser-extension/_locales/fr/messages.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/browser-extension/_locales/fr/messages.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
6 changes: 5 additions & 1 deletion examples/browser-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
"check": "tsc --noEmit",
"extract": "saykit extract",
"build": "vite build",
"dev": "vite build --watch"
"dev": "vite build --watch",
"compile": "saykit compile",
"predev": "saykit compile",
"prebuild": "saykit compile",
"precheck": "saykit compile"
},
"dependencies": {
"saykit": "workspace:^"
Expand Down
6 changes: 3 additions & 3 deletions examples/browser-extension/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createCatalogue } from 'saykit';
import de from '../_locales/de/messages.json';
import en from '../_locales/en/messages.json';
import fr from '../_locales/fr/messages.json';
import de from '../_locales/de/messages.js';
import en from '../_locales/en/messages.js';
import fr from '../_locales/fr/messages.js';

export const locales = ['en', 'fr', 'de'] as const;
export type Locale = (typeof locales)[number];
Expand Down
6 changes: 5 additions & 1 deletion examples/carbon/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
"check": "tsc --noEmit",
"extract": "saykit extract",
"build": "tsdown",
"dev": "wrangler dev"
"dev": "wrangler dev",
"compile": "saykit compile",
"predev": "saykit compile",
"prebuild": "saykit compile",
"precheck": "saykit compile"
},
"dependencies": {
"@buape/carbon": "0.16.0",
Expand Down
8 changes: 4 additions & 4 deletions examples/carbon/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createWithSay } from '@saykit/carbon';
import { createCatalogue } from 'saykit';
import de from './locales/de.json';
import en from './locales/en-US.json';
import fr from './locales/fr.json';
import ja from './locales/ja.json';
import de from './locales/de.js';
import en from './locales/en-US.js';
import fr from './locales/fr.js';
import ja from './locales/ja.js';

export const locales = ['en-US', 'fr', 'de', 'ja'] as const;
export type Locale = (typeof locales)[number];
Expand Down
2 changes: 0 additions & 2 deletions examples/carbon/src/locales/de.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/carbon/src/locales/de.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/carbon/src/locales/en-US.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/carbon/src/locales/en-US.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/carbon/src/locales/fr.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/carbon/src/locales/fr.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/carbon/src/locales/ja.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/carbon/src/locales/ja.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
6 changes: 5 additions & 1 deletion examples/custom-formatter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
"check": "tsc --noEmit",
"extract": "saykit extract",
"build": "tsdown",
"start": "node dist/main.mjs"
"start": "node dist/main.mjs",
"compile": "saykit compile",
"prebuild": "saykit compile",
"precheck": "saykit compile",
"prestart": "saykit compile"
},
"dependencies": {
"saykit": "workspace:^",
Expand Down
6 changes: 3 additions & 3 deletions examples/custom-formatter/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createCatalogue } from 'saykit';
import de from './locales/de.yml';
import en from './locales/en.yml';
import fr from './locales/fr.yml';
import de from './locales/de.js';
import en from './locales/en.js';
import fr from './locales/fr.js';

export const locales = ['en', 'fr', 'de'] as const;
export type Locale = (typeof locales)[number];
Expand Down
4 changes: 4 additions & 0 deletions examples/custom-formatter/src/locales/de.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/custom-formatter/src/locales/de.d.yml.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/custom-formatter/src/locales/en.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/custom-formatter/src/locales/en.d.yml.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/custom-formatter/src/locales/fr.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/custom-formatter/src/locales/fr.d.yml.ts

This file was deleted.

2 changes: 1 addition & 1 deletion examples/expo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ would otherwise produce loose strings between elements.

Metro is not a Vite/Rollup-family bundler, so `unplugin-saykit` does not apply. Metro compiles every
module through Babel, and `babel-plugin-saykit` hooks in there instead, doing the same two jobs:
rewriting the macros, and inlining `import en from './locales/en.json'` as a plain object.
rewriting the macros, and inlining `import en from './locales/en.js'` as a plain object.

```js
module.exports = function babelConfig(api) {
Expand Down
2 changes: 1 addition & 1 deletion examples/expo/babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ module.exports = function babelConfig(api) {

return {
presets: ['babel-preset-expo'],
plugins: [['saykit', { catalogues: 'module' }]],
plugins: ['saykit'],
};
};
3 changes: 1 addition & 2 deletions examples/expo/metro.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const path = require('node:path');
const { getDefaultConfig } = require('expo/metro-config');
const { withSayKit } = require('babel-plugin-saykit/metro');

const config = withSayKit(getDefaultConfig(__dirname));
const config = getDefaultConfig(__dirname);

// Two copies of React break hooks, so force every request to this app's copy
config.resolver.resolveRequest = (context, moduleName, platform) => {
Expand Down
5 changes: 4 additions & 1 deletion examples/expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
"scripts": {
"check": "tsc --noEmit",
"extract": "saykit extract",
"dev": "expo start"
"dev": "expo start",
"compile": "saykit compile",
"predev": "saykit compile",
"precheck": "saykit compile"
},
"dependencies": {
"@formatjs/intl-getcanonicallocales": "^3.2.11",
Expand Down
6 changes: 3 additions & 3 deletions examples/expo/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getLocales } from 'expo-localization';
import { createCatalogue, createStore } from 'saykit';
import en from './locales/en.json';
import fr from './locales/fr.json';
import ja from './locales/ja.json';
import en from './locales/en.js';
import fr from './locales/fr.js';
import ja from './locales/ja.js';

export const locales = ['en', 'fr', 'ja'] as const;
export type Locale = (typeof locales)[number];
Expand Down
2 changes: 0 additions & 2 deletions examples/expo/src/locales/en.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/expo/src/locales/en.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/expo/src/locales/fr.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/expo/src/locales/fr.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
2 changes: 0 additions & 2 deletions examples/expo/src/locales/ja.d.json.ts

This file was deleted.

4 changes: 4 additions & 0 deletions examples/expo/src/locales/ja.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Message } from 'saykit';

declare const messages: Record<string, Message>;
export default messages;
9 changes: 5 additions & 4 deletions examples/nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ The component you write is identical in both cases:
</Say>
```

Because both halves are fed from the same view, with the client provider
reading its locale and messages straight off it, server output and client hydration cannot disagree
about which locale is active.
Because both halves are fed from the same view, with the client provider reading its locale and
messages straight off it, server output and client hydration cannot disagree about which locale is
active. Messages compile to data rather than to functions, so they cross the boundary as the JSON
they already are.

## Why `src/config.ts` exists separately

Expand All @@ -56,7 +57,7 @@ Next.js compiles with its own toolchain, so the macros are rewritten by `babel-p
{ "presets": ["next/babel"], "plugins": ["saykit"] }
```

The plugin also rewrites `import en from './locales/en.po'` into an inline object. It requires a
The plugin also rewrites `import en from './locales/en.js'` into an inline object. It requires a
**default** import for catalogue files and throws on a named one, which is the intended failure
mode, not a bug.

Expand Down
5 changes: 2 additions & 3 deletions examples/nextjs/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
import { withSayKit } from 'babel-plugin-saykit/next';

export default withSayKit({});
/** @type {import('next').NextConfig} */
export default {};
7 changes: 6 additions & 1 deletion examples/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
"extract": "saykit extract",
"dev": "next dev",
"build": "next build",
"start": "next start"
"start": "next start",
"compile": "saykit compile",
"predev": "saykit compile",
"prebuild": "saykit compile",
"precheck": "saykit compile",
"prestart": "saykit compile"
},
"dependencies": {
"@saykit/react": "workspace:^",
Expand Down
6 changes: 3 additions & 3 deletions examples/nextjs/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createWithSay } from '@saykit/react/server';
import { createCatalogue } from 'saykit';
import en from './locales/en.po';
import fr from './locales/fr.po';
import pl from './locales/pl.po';
import en from './locales/en.js';
import fr from './locales/fr.js';
import pl from './locales/pl.js';

export const catalogue = createCatalogue({ en, fr, pl });

Expand Down
Loading
Loading