Skip to content

Commit c7b1e4d

Browse files
chore: [app dir bootstrapping 6] server-side translations (calcom#11995)
Co-authored-by: zomars <[email protected]>
1 parent 139a7c8 commit c7b1e4d

File tree

7 files changed

+78
-12
lines changed

7 files changed

+78
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
diff --git a/dist/commonjs/serverSideTranslations.js b/dist/commonjs/serverSideTranslations.js
2+
index bcad3d02fbdfab8dacb1d85efd79e98623a0c257..fff668f598154a13c4030d1b4a90d5d9c18214ad 100644
3+
--- a/dist/commonjs/serverSideTranslations.js
4+
+++ b/dist/commonjs/serverSideTranslations.js
5+
@@ -36,7 +36,6 @@ var _fs = _interopRequireDefault(require("fs"));
6+
var _path = _interopRequireDefault(require("path"));
7+
var _createConfig = require("./config/createConfig");
8+
var _node = _interopRequireDefault(require("./createClient/node"));
9+
-var _appWithTranslation = require("./appWithTranslation");
10+
var _utils = require("./utils");
11+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
12+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
13+
@@ -110,12 +109,8 @@ var serverSideTranslations = /*#__PURE__*/function () {
14+
lng: initialLocale
15+
}));
16+
localeExtension = config.localeExtension, localePath = config.localePath, fallbackLng = config.fallbackLng, reloadOnPrerender = config.reloadOnPrerender;
17+
- if (!reloadOnPrerender) {
18+
- _context.next = 18;
19+
- break;
20+
- }
21+
_context.next = 18;
22+
- return _appWithTranslation.globalI18n === null || _appWithTranslation.globalI18n === void 0 ? void 0 : _appWithTranslation.globalI18n.reloadResources();
23+
+ return void 0;
24+
case 18:
25+
_createClient = (0, _node["default"])(_objectSpread(_objectSpread({}, config), {}, {
26+
lng: initialLocale

apps/web/playwright/locale.e2e.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,14 @@ test.describe("unauthorized user sees correct translations (pt)", async () => {
150150

151151
test.describe("unauthorized user sees correct translations (pt-br)", async () => {
152152
test.use({
153-
locale: "pt-br",
153+
locale: "pt-BR",
154154
});
155155

156156
test("should use correct translations and html attributes", async ({ page }) => {
157157
await page.goto("/");
158158
await page.waitForLoadState("load");
159159

160-
await page.locator("html[lang=pt-br]").waitFor({ state: "attached" });
160+
await page.locator("html[lang=pt-BR]").waitFor({ state: "attached" });
161161
await page.locator("html[dir=ltr]").waitFor({ state: "attached" });
162162

163163
{
@@ -181,7 +181,8 @@ test.describe("unauthorized user sees correct translations (es-419)", async () =
181181
await page.goto("/");
182182
await page.waitForLoadState("load");
183183

184-
await page.locator("html[lang=es-419]").waitFor({ state: "attached" });
184+
// es-419 is disabled in i18n config, so es should be used as fallback
185+
await page.locator("html[lang=es]").waitFor({ state: "attached" });
185186
await page.locator("html[dir=ltr]").waitFor({ state: "attached" });
186187

187188
{

apps/web/server/lib/ssg.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,14 @@ export async function ssgInit<TParams extends { locale?: string }>(opts: GetStat
3737
},
3838
});
3939

40-
// always preload i18n
41-
await ssg.viewer.public.i18n.fetch({ locale, CalComVersion: CALCOM_VERSION });
40+
// i18n translations are already retrieved from serverSideTranslations call, there is no need to run a i18n.fetch
41+
// we can set query data directly to the queryClient
42+
const queryKey = [
43+
["viewer", "public", "i18n"],
44+
{ input: { locale, CalComVersion: CALCOM_VERSION }, type: "query" },
45+
];
46+
47+
ssg.queryClient.setQueryData(queryKey, { i18n: _i18n });
4248

4349
return ssg;
4450
}

apps/web/server/lib/ssr.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,17 @@ export async function ssrInit(context: GetServerSidePropsContext, options?: { no
2525
ctx: { ...ctx, locale, i18n },
2626
});
2727

28+
// i18n translations are already retrieved from serverSideTranslations call, there is no need to run a i18n.fetch
29+
// we can set query data directly to the queryClient
30+
const queryKey = [
31+
["viewer", "public", "i18n"],
32+
{ input: { locale, CalComVersion: CALCOM_VERSION }, type: "query" },
33+
];
34+
if (!options?.noI18nPreload) {
35+
ssr.queryClient.setQueryData(queryKey, { i18n });
36+
}
37+
2838
await Promise.allSettled([
29-
// always preload "viewer.public.i18n"
30-
!options?.noI18nPreload
31-
? ssr.viewer.public.i18n.prefetch({ locale, CalComVersion: CALCOM_VERSION })
32-
: Promise.resolve({}),
3339
// So feature flags are available on first render
3440
ssr.viewer.features.map.prefetch(),
3541
// Provides a better UX to the users who have already upgraded.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@
108108
"@types/node": "16.9.1",
109109
"@types/react": "18.0.26",
110110
"@types/react-dom": "^18.0.9",
111-
"libphonenumber-js@^1.10.12": "patch:libphonenumber-js@npm%3A1.10.12#./.yarn/patches/libphonenumber-js-npm-1.10.12-51c84f8bf1.patch"
111+
"libphonenumber-js@^1.10.12": "patch:libphonenumber-js@npm%3A1.10.12#./.yarn/patches/libphonenumber-js-npm-1.10.12-51c84f8bf1.patch",
112+
"next-i18next@^13.2.2": "patch:next-i18next@npm%3A13.3.0#./.yarn/patches/next-i18next-npm-13.3.0-bf25b0943c.patch"
112113
},
113114
"lint-staged": {
114115
"(apps|packages)/**/*.{js,ts,jsx,tsx}": [

packages/features/auth/lib/getLocale.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { parse } from "accept-language-parser";
2+
import { lookup } from "bcp-47-match";
23
import type { GetTokenParams } from "next-auth/jwt";
34
import { getToken } from "next-auth/jwt";
45

6+
//@ts-expect-error no type definitions
7+
import { i18n } from "@calcom/web/next-i18next.config";
8+
59
/**
610
* This is a slimmed down version of the `getServerSession` function from
711
* `next-auth`.
@@ -40,5 +44,9 @@ export const getLocale = async (req: GetTokenParams["req"]): Promise<string> =>
4044
// the regex underneath is more permissive
4145
const testedRegion = /^[a-zA-Z0-9]+$/.test(region) ? region : "";
4246

43-
return `${testedCode}${testedRegion !== "" ? "-" : ""}${testedRegion}`;
47+
const requestedLocale = `${testedCode}${testedRegion !== "" ? "-" : ""}${testedRegion}`;
48+
49+
// use fallback to closest supported locale.
50+
// for instance, es-419 will be transformed to es
51+
return lookup(i18n.locales, requestedLocale) ?? requestedLocale;
4452
};

yarn.lock

+19-1
Original file line numberDiff line numberDiff line change
@@ -29419,7 +29419,7 @@ __metadata:
2941929419
languageName: node
2942029420
linkType: hard
2942129421

29422-
"next-i18next@npm:^13.2.2":
29422+
"next-i18next@npm:13.3.0":
2942329423
version: 13.3.0
2942429424
resolution: "next-i18next@npm:13.3.0"
2942529425
dependencies:
@@ -29437,6 +29437,24 @@ __metadata:
2943729437
languageName: node
2943829438
linkType: hard
2943929439

29440+
"next-i18next@patch:next-i18next@npm%3A13.3.0#./.yarn/patches/next-i18next-npm-13.3.0-bf25b0943c.patch::locator=calcom-monorepo%40workspace%3A.":
29441+
version: 13.3.0
29442+
resolution: "next-i18next@patch:next-i18next@npm%3A13.3.0#./.yarn/patches/next-i18next-npm-13.3.0-bf25b0943c.patch::version=13.3.0&hash=bcbde7&locator=calcom-monorepo%40workspace%3A."
29443+
dependencies:
29444+
"@babel/runtime": ^7.20.13
29445+
"@types/hoist-non-react-statics": ^3.3.1
29446+
core-js: ^3
29447+
hoist-non-react-statics: ^3.3.2
29448+
i18next-fs-backend: ^2.1.1
29449+
peerDependencies:
29450+
i18next: ^22.0.6
29451+
next: ">= 12.0.0"
29452+
react: ">= 17.0.2"
29453+
react-i18next: ^12.2.0
29454+
checksum: 7dcb7e2ec14a0164e2c803b5eb4be3d3198ff0db266fecd6225dfa99ec53bf923fe50230c413f2e9b9a795266fb4e31f129572865181df1eadcf8721ad138b3e
29455+
languageName: node
29456+
linkType: hard
29457+
2944029458
"next-seo@npm:^6.0.0":
2944129459
version: 6.1.0
2944229460
resolution: "next-seo@npm:6.1.0"

0 commit comments

Comments
 (0)