Skip to content

Commit 16af185

Browse files
committed
feat: make the structure of server and client packages more similar
The export were the same, but it is a bit confusing when the hook is a separate file in one implementation and in index in another.
1 parent f2c4228 commit 16af185

2 files changed

Lines changed: 81 additions & 82 deletions

File tree

cmp/compiler/src/react/server/index.ts

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -12,87 +12,6 @@
1212
*
1313
* @module @lingo.dev/compiler/react (server)
1414
*/
15-
16-
import type { ReactNode } from "react";
17-
import { use } from "react";
18-
import { getServerLocale } from "@lingo.dev/compiler/locale/server";
19-
import { fetchTranslationsOnServer } from "../server-only/translations";
20-
import {
21-
renderRichText,
22-
type RichTextParams,
23-
} from "../shared/render-rich-text";
24-
import { logger } from "../../utils/logger";
25-
import type { TranslationHook } from "../types";
26-
27-
// TODO (AleksandrSl 01/12/2025): Should we add back the cache?
28-
const getTranslations = async (hashes: string[]) => {
29-
// 1. Resolve locale (framework-specific)
30-
const locale = await getServerLocale();
31-
32-
// 2. Fetch translations (universal)
33-
const translations = await fetchTranslationsOnServer(locale, hashes);
34-
35-
logger.debug(
36-
`Server. The translations for locale ${locale} are: ${JSON.stringify(translations)}`,
37-
);
38-
39-
return {
40-
locale,
41-
translations,
42-
};
43-
};
44-
45-
/**
46-
* Server-side translation hook
47-
*
48-
* Works in Server Components WITHOUT async/await!
49-
* Uses React's use() hook to unwrap the cached promise.
50-
*
51-
* This hook has the SAME signature as the client-side version,
52-
* making components truly isomorphic.
53-
*
54-
* @param hashes - List of translation hashes used in component (injected by compiler)
55-
* @returns Translation function
56-
*
57-
* @example
58-
* ```tsx
59-
* // Works in Server Components (no async needed!)
60-
* export default function ServerPage() {
61-
* const t = useTranslation(['hash_abc', 'hash_def']);
62-
* return <h1>{t('hash_abc', 'Welcome')}</h1>;
63-
* }
64-
*
65-
* // Also works in Client Components (via conditional exports)
66-
* 'use client';
67-
* export default function ClientPage() {
68-
* const t = useTranslation(['hash_abc', 'hash_def']);
69-
* return <h1>{t('hash_abc', 'Welcome')}</h1>;
70-
* }
71-
* ```
72-
*/
73-
export const useTranslation: TranslationHook = (hashes: string[]) => {
74-
const { locale, translations } = use(getTranslations(hashes));
75-
logger.debug(
76-
`Server. The translations for locale ${locale} are: ${JSON.stringify(translations)}`,
77-
);
78-
79-
return {
80-
t: (
81-
hash: string,
82-
source: string,
83-
params?: RichTextParams,
84-
): string | ReactNode => {
85-
const text = translations[hash] || source;
86-
87-
if (!params) {
88-
return text;
89-
}
90-
91-
return renderRichText(text, params);
92-
},
93-
locale,
94-
};
95-
};
96-
9715
export { TranslationProvider } from "./ServerTranslationProvider";
9816
export { LocaleSwitcher } from "../shared/LocaleSwitcher";
17+
export { useTranslation } from "./useTranslation";
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import type { ReactNode } from "react";
2+
import { use } from "react";
3+
import { getServerLocale } from "@lingo.dev/compiler/locale/server";
4+
import { fetchTranslationsOnServer } from "../server-only/translations";
5+
import {
6+
renderRichText,
7+
type RichTextParams,
8+
} from "../shared/render-rich-text";
9+
import { logger } from "../../utils/logger";
10+
import type { TranslationHook } from "../types";
11+
12+
// TODO (AleksandrSl 01/12/2025): Should we add back the cache?
13+
const getTranslations = async (hashes: string[]) => {
14+
// 1. Resolve locale (framework-specific)
15+
const locale = await getServerLocale();
16+
17+
// 2. Fetch translations (universal)
18+
const translations = await fetchTranslationsOnServer(locale, hashes);
19+
20+
logger.debug(
21+
`Server. The translations for locale ${locale} are: ${JSON.stringify(translations)}`,
22+
);
23+
24+
return {
25+
locale,
26+
translations,
27+
};
28+
};
29+
30+
/**
31+
* Server-side translation hook
32+
*
33+
* Works in Server Components WITHOUT async/await!
34+
* Uses React's use() hook to unwrap the cached promise.
35+
*
36+
* This hook has the SAME signature as the client-side version,
37+
* making components truly isomorphic.
38+
*
39+
* @param hashes - List of translation hashes used in component (injected by compiler)
40+
* @returns Translation function
41+
*
42+
* @example
43+
* ```tsx
44+
* // Works in Server Components (no async needed!)
45+
* export default function ServerPage() {
46+
* const t = useTranslation(['hash_abc', 'hash_def']);
47+
* return <h1>{t('hash_abc', 'Welcome')}</h1>;
48+
* }
49+
*
50+
* // Also works in Client Components (via conditional exports)
51+
* 'use client';
52+
* export default function ClientPage() {
53+
* const t = useTranslation(['hash_abc', 'hash_def']);
54+
* return <h1>{t('hash_abc', 'Welcome')}</h1>;
55+
* }
56+
* ```
57+
*/
58+
export const useTranslation: TranslationHook = (hashes: string[]) => {
59+
const { locale, translations } = use(getTranslations(hashes));
60+
logger.debug(
61+
`Server. The translations for locale ${locale} are: ${JSON.stringify(translations)}`,
62+
);
63+
64+
return {
65+
t: (
66+
hash: string,
67+
source: string,
68+
params?: RichTextParams,
69+
): string | ReactNode => {
70+
const text = translations[hash] || source;
71+
72+
if (!params) {
73+
return text;
74+
}
75+
76+
return renderRichText(text, params);
77+
},
78+
locale,
79+
};
80+
};

0 commit comments

Comments
 (0)