Skip to content

Commit d7aad33

Browse files
committed
chore: migrate translation extraction to i18next-cli
1 parent 7809c69 commit d7aad33

33 files changed

+1830
-1987
lines changed

.github/actions/setup-node/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ inputs:
55
node-version:
66
description: 'Specify Node version'
77
required: false
8-
default: '22'
8+
default: '24'
99

1010
runs:
1111
using: 'composite'

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Root configs:
4242
- codecov.yml
4343
- commitlint.config.mjs
4444
- eslint.config.mjs,
45-
- i18next-parser.config.js
45+
- i18next.config.ts
4646
- jest.config.js
4747
- jest.config.js
4848
- playwright.config.ts

i18next-parser.config.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

i18next.config.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { defineConfig } from 'i18next-cli';
2+
3+
export default defineConfig({
4+
locales: ['de', 'en', 'es', 'fr', 'hi', 'it', 'ja', 'ko', 'nl', 'pt', 'ru', 'tr'],
5+
extract: {
6+
defaultNS: false,
7+
extractFromComments: false,
8+
functions: ['t', '*.t'],
9+
input: ['./src/**/*.{tsx,ts}'],
10+
keySeparator: false,
11+
nsSeparator: false,
12+
output: 'src/i18n/{{language}}.json',
13+
preservePatterns: [
14+
// to preserve a whole group
15+
'timestamp/*',
16+
17+
// or exact key if you want :
18+
// 'timestamp/DateSeparator',
19+
20+
// or if you’re using explicit namespaces:
21+
// 'translation:timestamp/DateSeparator',
22+
],
23+
removeUnusedKeys: false,
24+
},
25+
types: {
26+
input: ['locales/{{language}}/{{namespace}}.json'],
27+
output: 'src/types/i18next.d.ts',
28+
},
29+
});

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@
223223
"eslint-plugin-sort-destructure-keys": "^2.0.0",
224224
"globals": "^15.13.0",
225225
"husky": "^8.0.3",
226-
"i18next-parser": "^9.3.0",
226+
"i18next-cli": "^1.31.0",
227227
"jest": "^29.7.0",
228228
"jest-axe": "^8.0.0",
229229
"jest-environment-jsdom": "^29.7.0",
@@ -242,7 +242,7 @@
242242
"scripts": {
243243
"build": "rm -rf dist && yarn build-translations && yarn bundle",
244244
"bundle": "concurrently ./scripts/bundle-esm.mjs ./scripts/copy-css.sh scripts/bundle-cjs.mjs",
245-
"build-translations": "i18next",
245+
"build-translations": "i18next-cli extract",
246246
"coverage": "jest --collectCoverage && codecov",
247247
"lint": "yarn prettier --list-different && yarn eslint && yarn validate-translations",
248248
"lint-fix": "yarn prettier-fix && yarn eslint-fix",

src/components/Attachment/AttachmentActions.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22
import type { Action, Attachment } from 'stream-chat';
33

44
import { useTranslationContext } from '../../context';
@@ -26,6 +26,15 @@ const UnMemoizedAttachmentActions = (props: AttachmentActionsProps) => {
2626
value?: string,
2727
) => actionHandler?.(name, value, event);
2828

29+
const knownActionText = useMemo<Record<string, string>>(
30+
() => ({
31+
Cancel: t('Cancel'),
32+
Send: t('Send'),
33+
Shuffle: t('Shuffle'),
34+
}),
35+
[t],
36+
);
37+
2938
return (
3039
<div className='str-chat__message-attachment-actions'>
3140
<div className='str-chat__message-attachment-actions-form'>
@@ -38,7 +47,7 @@ const UnMemoizedAttachmentActions = (props: AttachmentActionsProps) => {
3847
key={`${id}-${action.value}`}
3948
onClick={(event) => handleActionClick(event, action.name, action.value)}
4049
>
41-
{action.text ? t(action.text) : null}
50+
{action.text ? (knownActionText[action.text] ?? t(action.text)) : null}
4251
</button>
4352
))}
4453
</div>

src/components/DateSeparator/DateSeparator.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const UnMemoizedDateSeparator = (props: DateSeparatorProps) => {
3535
messageCreatedAt,
3636
t,
3737
tDateTimeParser,
38+
// todo: how to register it
3839
timestampTranslationKey: 'timestamp/DateSeparator',
3940
});
4041

src/components/Message/ReminderNotification.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ export const ReminderNotification = ({ reminder }: ReminderNotificationProps) =>
3333
<span>
3434
{isBehindRefreshBoundary
3535
? t('Due since {{ dueSince }}', {
36-
dueSince: t(`timestamp/ReminderNotification`, {
36+
dueSince: t('timestamp/ReminderNotification', {
3737
timestamp: reminder.remindAt,
3838
}),
3939
})
40-
: t(`Due {{ timeLeft }}`, {
40+
: t('Due {{ timeLeft }}', {
4141
timeLeft: t('duration/Message reminder', {
4242
milliseconds: timeLeftMs,
4343
}),

src/components/Message/hooks/useMuteHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const useMuteHandler = (
4545

4646
notify(
4747
successMessage ||
48-
t(`{{ user }} has been muted`, {
48+
t('{{ user }} has been muted', {
4949
user: message.user.name || message.user.id,
5050
}),
5151
'success',
@@ -61,7 +61,7 @@ export const useMuteHandler = (
6161
try {
6262
await client.unmuteUser(message.user.id);
6363

64-
const fallbackMessage = t(`{{ user }} has been unmuted`, {
64+
const fallbackMessage = t('{{ user }} has been unmuted', {
6565
user: message.user.name || message.user.id,
6666
});
6767

src/components/MessageInput/AttachmentPreviewList/AttachmentPreviewList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { UnsupportedAttachmentPreview as DefaultUnknownAttachmentPreview } from
1414
import type { VoiceRecordingPreviewProps } from './VoiceRecordingPreview';
1515
import { VoiceRecordingPreview as DefaultVoiceRecordingPreview } from './VoiceRecordingPreview';
1616
import type { FileAttachmentPreviewProps } from './FileAttachmentPreview';
17-
import { FileAttachmentPreview as DefaultFilePreview } from './FileAttachmentPreview';
17+
import DefaultFilePreview from './FileAttachmentPreview';
1818
import type { ImageAttachmentPreviewProps } from './ImageAttachmentPreview';
1919
import { ImageAttachmentPreview as DefaultImagePreview } from './ImageAttachmentPreview';
2020
import { useAttachmentsForPreview, useMessageComposer } from '../hooks';

0 commit comments

Comments
 (0)