refactor: replace i18n HTTP requests with build-time bundling (#22422)
* refactor: replace i18n HTTP requests with build-time bundling - Create translationBundler.ts for build-time translation loading - Replace HTTP fetch in loadTranslations with file system reads - Add CalComVersion cache invalidation to prevent stale translations - Fix TypeScript errors in booking page components - Eliminate 60s timeout issues by removing network dependency Resolves translation timeout issues by bundling translations at build time instead of making runtime HTTP requests to /static/locales/ endpoints. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: move i18n files back to packages/lib/server with proper imports - Move i18n.ts and translationBundler.ts back to packages/lib/server/ - Replace all relative imports with @calcom/lib/server/i18n pattern - Fix LOCALES_PATH to point to correct directory - Maintain optimized serverless-friendly translation loading Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * refactor: move locale files to packages/lib/server to eliminate circular deps - Move all locale files from apps/web/public/static/locales to packages/lib/server/locales - Create copy-locales-static.js script to copy files during build - Update all references to use new location for build-time access - Maintain public folder copying for Next.js runtime access - Update platform atoms, scripts, and config files - Fix copy script relative path issue Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: update test imports after locale refactor - Fix import paths in test files updated by pre-commit hooks - Ensure all tests use correct locale import paths Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: revert import paths from @calcom/web/lib/i18n to @calcom/lib/server/i18n - Revert all test file imports back to @calcom/lib/server/i18n as requested - Addresses GitHub comment feedback to stick with packages/lib/server location - Fixes import paths in 6 test files that were incorrectly changed Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: update vite config alias to use new locale path - Update @calcom/web/public/static/locales/en/common.json to @calcom/lib/server/locales/en/common.json - Addresses GitHub comment about updating platform atoms vite config - Maintains correct path resolution after locale files moved to packages/lib/server Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: update translationBundler path resolution for production builds - Use process.cwd() instead of __dirname for locale file path resolution - Ensures locale files can be found in both development and production environments - Fixes E2E test failures caused by missing locale files in .next/server/chunks/ Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use relative path resolution for locale files in translationBundler - Change from process.cwd() to __dirname with relative paths - Ensures locale files can be found in both development and production environments - Fixes E2E test failures caused by incorrect path resolution in Next.js builds Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use process.cwd() for locale path resolution in production builds - Change from __dirname to process.cwd() with relative paths - Ensures locale files can be found when bundled into Next.js server chunks - Fixes E2E test failures caused by incorrect path resolution in production environment - Follows same pattern used in getStaticProps.tsx for cross-package file access Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use path.resolve pattern from sendVerificationRequest for locale access - Change from process.cwd() to path.resolve(process.cwd(), '..', '..', 'packages/lib/server/locales') - Follows same pattern used in sendVerificationRequest.ts for cross-environment file access - Should resolve E2E test failures by ensuring locale files can be found when bundled into Next.js server chunks - Pattern navigates up from current working directory to reach packages directory consistently Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use dynamic monorepo root detection for locale path resolution - Replace relative path resolution with dynamic monorepo root finder - Ensures locale files can be found from any working directory (root, apps/web, apps/api/v2) - Update API v2 i18n config to use new locale path - Fixes remaining E2E test failures in API v2 and E2E (1/4) test suites Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use require.resolve(__filename) for robust path resolution in all contexts - Replace __dirname with require.resolve(__filename) in monorepo root detection - Ensures locale files can be found when running from any working directory - Fixes E2E API v2 test failures where __dirname resolves to '.' instead of actual file path Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * Revert "fix: use require.resolve(__filename) for robust path resolution in all contexts" This reverts commit b37d8226000da8f7d5fb98b83dd0e95a53d45372. * fix: update copied locale files after translationBundler path resolution fix - Copy script updated all locale files in public directory - Ensures E2E tests have access to latest locale files - Fixes regression where all E2E tests were failing Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * feat: remove existing locale files to establish copy script as single source of truth - Delete all common.json files from apps/web/public/static/locales/ - Eliminates developer confusion about which files are authoritative - copy-locales-static.js script now clearly the only mechanism for populating public folder - packages/lib/server/locales/ remains the definitive source of truth for translations Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * add comment * refactor: simplify findMonorepoRoot by removing redundant fallback loop - Remove unnecessary second while loop using process.cwd() - The first loop from __dirname will always find the monorepo root - Add clear error message for fail-fast behavior if repo structure is corrupted - Improves code clarity and maintainability Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * feat: integrate updated translations from main branch - Restore all common.json files from main branch to apps/web/public/static/locales/ - Overwrite packages/lib/server/locales/ with up-to-date translation content - Resolve merge conflicts using Benny's safer 2-step approach - Ensure translation source of truth remains in packages/lib/server/locales/ - Complete safer conflict resolution to eliminate merge conflicts on PR #22422 Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * chore: update package.json and yarn.lock after translation integration - Update dependencies after ts-node installation for pre-commit hooks - Ensure yarn.lock reflects current dependency state - Complete translation integration process Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * feat: remove duplicate locale files from apps/web to establish single source of truth - Delete all common.json files from apps/web/public/static/locales/ - Maintain packages/lib/server/locales/ as the single source of truth for translations - copy-locales-static.js script will populate public folder during build process - Complete Benny's safer 2-step approach: restore from main, then remove duplicates - Resolve merge conflicts and eliminate developer confusion about translation file locations Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: hbjORbj <sldisek783@gmail.com>
This commit is contained in:
co-authored by
keith@cal.com <keithwillcode@gmail.com>
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
hbjORbj
parent
bd5e14b488
commit
163c7ff791
@@ -33,7 +33,7 @@ jobs:
|
||||
with:
|
||||
filters: |
|
||||
has-files-requiring-all-checks:
|
||||
- "!(**.md|.github/CODEOWNERS|docs/**|help/**|apps/web/public/static/locales/**/common.json)"
|
||||
- "!(**.md|.github/CODEOWNERS|docs/**|help/**|packages/lib/server/locales/**/common.json)"
|
||||
- name: Get Latest Commit SHA
|
||||
id: get_sha
|
||||
run: |
|
||||
|
||||
@@ -5,7 +5,7 @@ const i18nConfig = require("@calcom/config/next-i18next.config");
|
||||
/** @type {import("next-i18next").UserConfig} */
|
||||
const config = {
|
||||
...i18nConfig,
|
||||
localePath: path.resolve("../../web/public/static/locales"),
|
||||
localePath: path.resolve("../../packages/lib/server/locales"),
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
||||
@@ -32,7 +32,7 @@ const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
|
||||
const eventLocale = props.eventData?.interfaceLanguage;
|
||||
const ns = "common";
|
||||
let translations;
|
||||
let translations: Record<string, string> = {};
|
||||
if (eventLocale) {
|
||||
const ns = "common";
|
||||
translations = await loadTranslations(eventLocale, ns);
|
||||
|
||||
@@ -68,7 +68,7 @@ const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
|
||||
const eventLocale = props.eventData?.interfaceLanguage;
|
||||
const ns = "common";
|
||||
let translations;
|
||||
let translations: Record<string, string> = {};
|
||||
if (eventLocale) {
|
||||
const ns = "common";
|
||||
translations = await loadTranslations(eventLocale, ns);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
require("dotenv").config({ path: "../../.env" });
|
||||
const englishTranslation = require("./public/static/locales/en/common.json");
|
||||
const englishTranslation = require("../../packages/lib/server/locales/en/common.json");
|
||||
const { withAxiom } = require("next-axiom");
|
||||
const { version } = require("./package.json");
|
||||
const {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"type-check": "tsc --pretty --noEmit",
|
||||
"type-check:ci": "tsc-absolute --pretty --noEmit",
|
||||
"sentry:release": "NODE_OPTIONS='--max-old-space-size=6144' node scripts/create-sentry-release.js",
|
||||
"copy-static": "node scripts/copy-app-store-static.js",
|
||||
"copy-static": "node scripts/copy-app-store-static.js && node scripts/copy-locales-static.js",
|
||||
"build": "yarn copy-static && next build && yarn sentry:release",
|
||||
"start": "next start",
|
||||
"lint": "eslint . --ignore-path .gitignore",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { loadJSON } from "./loadJSON";
|
||||
|
||||
// Provide an standalone localize utility not managed by next-i18n
|
||||
export async function localize(locale: string) {
|
||||
const localeModule = `../../public/static/locales/${locale}/common.json`;
|
||||
const localeModule = `../../../../packages/lib/server/locales/${locale}/common.json`;
|
||||
const localeMap = loadJSON(localeModule);
|
||||
return (message: string) => {
|
||||
if (message in localeMap) return localeMap[message];
|
||||
|
||||
@@ -3,7 +3,7 @@ import { join } from "path";
|
||||
|
||||
const TEMPLATE_LANGUAGE = "en";
|
||||
const SPECIFIC_LOCALES = process.argv.slice(2) || [];
|
||||
const LOCALES_PATH = join(__dirname, "../public/static/locales");
|
||||
const LOCALES_PATH = join(__dirname, "../../../packages/lib/server/locales");
|
||||
|
||||
const ALL_LOCALES = readdirSync(LOCALES_PATH);
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const glob = require("glob");
|
||||
|
||||
const copyLocalesStatic = () => {
|
||||
const localeFiles = glob.sync("../../packages/lib/server/locales/**/*.json", { nodir: true });
|
||||
|
||||
localeFiles.forEach((file) => {
|
||||
const relativePath = file.replace("../../packages/lib/server/locales/", "");
|
||||
|
||||
// Create destination directory if it doesn't exist
|
||||
const destDir = path.join(process.cwd(), "public", "static", "locales", path.dirname(relativePath));
|
||||
if (!fs.existsSync(destDir)) {
|
||||
fs.mkdirSync(destDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy file to destination
|
||||
const destPath = path.join(process.cwd(), "public", "static", "locales", relativePath);
|
||||
fs.copyFileSync(file, destPath);
|
||||
console.log(`Copied ${file} to ${destPath}`);
|
||||
});
|
||||
};
|
||||
|
||||
// Run the copy function
|
||||
copyLocalesStatic();
|
||||
@@ -23,7 +23,7 @@ const translationKeyRegex = /(?<!\w)(?:t\(("[^"]*")(?:,\s*\{[^}]*\})?\)|i18nKey=
|
||||
/** @type {import("i18n-unused/src/types/index.ts").RunOptions} */
|
||||
const config = {
|
||||
// localesPath: localePath, // uncomment to run on all locales (to calculate kb savings)
|
||||
localesPath: path.join("./apps/website", "/public/static/locales", "/en"),
|
||||
localesPath: path.join("./packages/lib/server/locales", "/en"),
|
||||
srcPath: "./apps/website",
|
||||
srcExtensions: ["ts", "tsx"],
|
||||
translationContextSeparator: ":",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
},
|
||||
"buckets": {
|
||||
"json": {
|
||||
"include": ["apps/web/public/static/locales/[locale]/common.json"]
|
||||
"include": ["packages/lib/server/locales/[locale]/common.json"]
|
||||
}
|
||||
},
|
||||
"$schema": "https://lingo.dev/schema/i18n.json"
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"prettier": "^2.8.6",
|
||||
"prismock": "^1.33.4",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsc-absolute": "^1.0.0",
|
||||
"typescript": "^5.7.2",
|
||||
"vitest": "^2.1.1",
|
||||
|
||||
@@ -2,9 +2,9 @@ import { createInstance } from "i18next";
|
||||
import { expect, test, describe } from "vitest";
|
||||
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import en from "@calcom/lib/server/locales/en/common.json";
|
||||
import { TimeFormat } from "@calcom/lib/timeFormat";
|
||||
import { WorkflowActions, WorkflowTemplates } from "@calcom/prisma/enums";
|
||||
import en from "@calcom/web/public/static/locales/en/common.json";
|
||||
|
||||
import { getTemplateBodyForAction } from "../actionHelperFunctions";
|
||||
import compareReminderBodyToTemplate from "../compareReminderBodyToTemplate";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
|
||||
import { parseRecurringEvent } from "./isRecurringEvent";
|
||||
import { getTranslation } from "./server/i18n";
|
||||
|
||||
type DestinationCalendar = {
|
||||
id: number;
|
||||
|
||||
+17
-22
@@ -1,6 +1,6 @@
|
||||
import { createInstance } from "i18next";
|
||||
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { CALCOM_VERSION } from "@calcom/lib/constants";
|
||||
|
||||
const translationCache = new Map<string, Record<string, string>>();
|
||||
const i18nInstanceCache = new Map<string, any>();
|
||||
@@ -10,27 +10,25 @@ const i18nInstanceCache = new Map<string, any>();
|
||||
* Implements caching to avoid redundant network requests
|
||||
* @returns {Promise<Record<string, string>>} English translations object or empty object on failure
|
||||
*/
|
||||
async function loadFallbackTranslations() {
|
||||
const cacheKey = "en-common";
|
||||
async function loadFallbackTranslations(): Promise<Record<string, string>> {
|
||||
const cacheKey = `en-common-${CALCOM_VERSION}`;
|
||||
|
||||
if (translationCache.has(cacheKey)) {
|
||||
return translationCache.get(cacheKey);
|
||||
return translationCache.get(cacheKey)!;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(`${WEBAPP_URL}/static/locales/en/common.json`, {
|
||||
cache: process.env.NODE_ENV === "production" ? "force-cache" : "no-store",
|
||||
});
|
||||
const { getBundledTranslations } = await import("./translationBundler");
|
||||
const translations = getBundledTranslations("en", "common");
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch fallback translations: ${res.status}`);
|
||||
if (Object.keys(translations).length === 0) {
|
||||
throw new Error("No English fallback translations found");
|
||||
}
|
||||
|
||||
const translations = await res.json();
|
||||
translationCache.set(cacheKey, translations);
|
||||
return translations;
|
||||
} catch (error) {
|
||||
console.error("Could not fetch fallback translations:", error);
|
||||
console.error("Could not load fallback translations:", error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -41,25 +39,22 @@ async function loadFallbackTranslations() {
|
||||
* @param {string} ns - The namespace for the translations
|
||||
* @returns {Promise<Record<string, string>>} Translations object or fallback translations on failure
|
||||
*/
|
||||
export async function loadTranslations(_locale: string, ns: string) {
|
||||
export async function loadTranslations(_locale: string, ns: string): Promise<Record<string, string>> {
|
||||
const locale = _locale === "zh" ? "zh-CN" : _locale;
|
||||
const cacheKey = `${locale}-${ns}`;
|
||||
const cacheKey = `${locale}-${ns}-${CALCOM_VERSION}`;
|
||||
|
||||
if (translationCache.has(cacheKey)) {
|
||||
return translationCache.get(cacheKey);
|
||||
return translationCache.get(cacheKey)!;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = `${WEBAPP_URL}/static/locales/${locale}/${ns}.json`;
|
||||
const response = await fetch(url, {
|
||||
cache: process.env.NODE_ENV === "production" ? "force-cache" : "no-store",
|
||||
});
|
||||
const { getBundledTranslations } = await import("./translationBundler");
|
||||
const translations = getBundledTranslations(locale, ns);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch translations: ${response.status}`);
|
||||
if (Object.keys(translations).length === 0) {
|
||||
throw new Error(`No translations found for ${locale}/${ns}`);
|
||||
}
|
||||
|
||||
const translations = await response.json();
|
||||
translationCache.set(cacheKey, translations);
|
||||
return translations;
|
||||
} catch (error) {
|
||||
@@ -76,7 +71,7 @@ export async function loadTranslations(_locale: string, ns: string) {
|
||||
* @returns {Promise<Function>} A translation function bound to the specified locale and namespace
|
||||
*/
|
||||
export const getTranslation = async (locale: string, ns: string) => {
|
||||
const cacheKey = `${locale}-${ns}`;
|
||||
const cacheKey = `${locale}-${ns}-${CALCOM_VERSION}`;
|
||||
if (i18nInstanceCache.has(cacheKey)) {
|
||||
return i18nInstanceCache.get(cacheKey).getFixedT(locale, ns);
|
||||
}
|
||||
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "تم حفظ مفتاح الترخيص بنجاح",
|
||||
"timezone_mismatch_tooltip": "أنت تشاهد التقرير بناءً على المنطقة الزمنية لملفك الشخصي ({{userTimezone}})، بينما متصفحك مضبوط على المنطقة الزمنية ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ أضف السلاسل الجديدة أعلاه هنا ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Lisenziya açarı uğurla saxlanıldı",
|
||||
"timezone_mismatch_tooltip": "Siz hesabatı profil saat qurşağınıza ({{userTimezone}}) əsasən görürsünüz, brauzeriniz isə başqa saat qurşağına ({{browserTimezone}}) təyin edilib",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni sətirləri bura əlavə edin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Лицензионният ключ е успешно записан",
|
||||
"timezone_mismatch_tooltip": "Преглеждате отчета според часовата зона на вашия профил ({{userTimezone}}), докато браузърът ви е настроен на часова зона ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Добавете новите си низове над този ред ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "লাইসেন্স কী সফলভাবে সংরক্ষিত হয়েছে",
|
||||
"timezone_mismatch_tooltip": "আপনি আপনার প্রোফাইল টাইমজোন ({{userTimezone}}) অনুসারে রিপোর্ট দেখছেন, যখন আপনার ব্রাউজার টাইমজোন ({{browserTimezone}}) এ সেট করা আছে",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑ুষান্ত"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Clau de llicència desada correctament",
|
||||
"timezone_mismatch_tooltip": "Esteu veient l'informe basat en la zona horària del vostre perfil ({{userTimezone}}), mentre que el vostre navegador està configurat a la zona horària ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Afegiu les vostres noves cadenes a dalt ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Licenční klíč byl úspěšně uložen",
|
||||
"timezone_mismatch_tooltip": "Prohlížíte si report na základě časového pásma vašeho profilu ({{userTimezone}}), zatímco váš prohlížeč je nastaven na časové pásmo ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Přidejte své nové řetězce nahoru ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Licensnøgle blev gemt med succes",
|
||||
"timezone_mismatch_tooltip": "Du ser rapporten baseret på din profils tidszone ({{userTimezone}}), mens din browser er indstillet til tidszonen ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Tilføj dine nye strenge ovenfor her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Το κλειδί άδειας αποθηκεύτηκε με επιτυχία",
|
||||
"timezone_mismatch_tooltip": "Βλέπετε την αναφορά με βάση τη ζώνη ώρας του προφίλ σας ({{userTimezone}}), ενώ ο περιηγητής σας είναι ρυθμισμένος στη ζώνη ώρας ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Προσθέστε τις νέες συμβολοσειρές σας πάνω από εδώ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -283,7 +283,7 @@
|
||||
"guests": "Guests",
|
||||
"guest": "Guest",
|
||||
"web_conferencing_details_to_follow": "Web conferencing details to follow in the confirmation email.",
|
||||
"confirmation":"Confirmation",
|
||||
"confirmation": "Confirmation",
|
||||
"what_booker_should_provide": "What your booker should provide to receive confirmations",
|
||||
"404_the_user": "The username",
|
||||
"username": "Username",
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Clave de licencia guardada correctamente",
|
||||
"timezone_mismatch_tooltip": "Estás viendo el informe basado en la zona horaria de tu perfil ({{userTimezone}}), mientras que tu navegador está configurado en la zona horaria ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agrega tus nuevas cadenas arriba de esta línea ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Clave de licencia guardada correctamente",
|
||||
"timezone_mismatch_tooltip": "Estás viendo el informe basado en la zona horaria de tu perfil ({{userTimezone}}), mientras que tu navegador está configurado en la zona horaria ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agregue sus nuevas cadenas arriba ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Litsentsivõti salvestati edukalt",
|
||||
"timezone_mismatch_tooltip": "Te vaatate aruannet oma profiili ajavööndi ({{userTimezone}}) alusel, samal ajal kui teie brauser on seadistatud ajavööndisse ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Lizentzia gakoa ondo gorde da",
|
||||
"timezone_mismatch_tooltip": "Txostena zure profileko ordu-zonaren arabera ikusten ari zara ({{userTimezone}}), zure nabigatzailea ordu-zona honetan ezarrita dagoen bitartean ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Gehitu zure kate berriak honen gainean ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Lisenssiavain tallennettu onnistuneesti",
|
||||
"timezone_mismatch_tooltip": "Tarkastelet raporttia profiilisi aikavyöhykkeen ({{userTimezone}}) mukaan, kun taas selaimesi on asetettu aikavyöhykkeelle ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Lisää uudet merkkijonot tämän yläpuolelle ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "מפתח הרישיון נשמר בהצלחה",
|
||||
"timezone_mismatch_tooltip": "אתה צופה בדוח על בסיס אזור הזמן של הפרופיל שלך ({{userTimezone}}), בעוד שהדפדפן שלך מוגדר לאזור זמן ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -453,4 +453,4 @@
|
||||
"reschedule_cta_short": "Zakažite ponovno ovdje.",
|
||||
"you_and_conjunction": "Vi &",
|
||||
"email_survey_triggered_by_workflow": "Ova anketa je pokrenuta Workflow-om u Calu."
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "A licenckulcs sikeresen mentve",
|
||||
"timezone_mismatch_tooltip": "A jelentést az Ön profiljában beállított időzóna ({{userTimezone}}) alapján tekinti meg, míg a böngészője a következő időzónára van állítva: {{browserTimezone}}",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adja hozzá az új karakterláncokat fent ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -166,4 +166,4 @@
|
||||
"reschedule_cta_short": "Jadwal ulang di sini.",
|
||||
"you_and_conjunction": "Anda &",
|
||||
"email_survey_triggered_by_workflow": "Survei ini dipicu oleh Workflow di Cal."
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Chiave di licenza salvata con successo",
|
||||
"timezone_mismatch_tooltip": "Stai visualizzando il report in base al fuso orario del tuo profilo ({{userTimezone}}), mentre il tuo browser è impostato sul fuso orario ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Aggiungi le tue nuove stringhe qui sopra ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "ライセンスキーが正常に保存されました",
|
||||
"timezone_mismatch_tooltip": "あなたはプロフィールのタイムゾーン({{userTimezone}})に基づいてレポートを表示していますが、ブラウザのタイムゾーンは({{browserTimezone}})に設定されています",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ この上に新しい文字列を追加してください ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "សោអាជ្ញាប័ណ្ណត្រូវបានរក្សាទុកដោយជោគជ័យ",
|
||||
"timezone_mismatch_tooltip": "អ្នកកំពុងមើលរបាយការណ៍ដោយផ្អែកលើតំបន់ពេលវេលាប្រវត្តិរូបរបស់អ្នក ({{userTimezone}}) ខណៈពេលដែលកម្មវិធីរុករករបស់អ្នកត្រូវបានកំណត់ទៅតំបន់ពេលវេលា ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ បន្ថែមខ្សែអក្សរថ្មីរបស់អ្នកនៅខាងលើនេះ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "라이선스 키가 성공적으로 저장되었습니다",
|
||||
"timezone_mismatch_tooltip": "프로필 시간대({{userTimezone}})를 기준으로 보고서를 보고 계시지만, 브라우저는 다른 시간대({{browserTimezone}})로 설정되어 있습니다",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 여기에 새 문자열을 추가하세요 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -162,4 +162,4 @@
|
||||
"reschedule_cta_short": "Pārzīmēt šeit.",
|
||||
"you_and_conjunction": "Jūs &",
|
||||
"email_survey_triggered_by_workflow": "Šo aptauju aktivizēja darbplūsma Cal."
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Licentiesleutel succesvol opgeslagen",
|
||||
"timezone_mismatch_tooltip": "Je bekijkt het rapport op basis van je profieltijdzone ({{userTimezone}}), terwijl je browser is ingesteld op tijdzone ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Voeg uw nieuwe strings hierboven toe ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Lisenssnøkkel lagret",
|
||||
"timezone_mismatch_tooltip": "Du ser rapporten basert på tidssonen i profilen din ({{userTimezone}}), mens nettleseren din er satt til tidssonen ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Legg til dine nye strenger over her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Chave de licença salva com sucesso",
|
||||
"timezone_mismatch_tooltip": "Você está visualizando o relatório com base no fuso horário do seu perfil ({{userTimezone}}), enquanto seu navegador está configurado para o fuso horário ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adicione suas novas strings aqui em cima ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Chave de licença salva com sucesso",
|
||||
"timezone_mismatch_tooltip": "Você está visualizando o relatório com base no fuso horário do seu perfil ({{userTimezone}}), enquanto seu navegador está configurado para o fuso horário ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Cheia de licență a fost salvată cu succes",
|
||||
"timezone_mismatch_tooltip": "Vizualizați raportul pe baza fusului orar al profilului dvs. ({{userTimezone}}), în timp ce browserul dvs. este setat pe fusul orar ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adăugați stringurile noi deasupra acestui rând ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Лицензионный ключ успешно сохранён",
|
||||
"timezone_mismatch_tooltip": "Вы просматриваете отчёт в часовом поясе вашего профиля ({{userTimezone}}), в то время как ваш браузер настроен на часовой пояс ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Добавьте строки выше ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Licenčný kľúč bol úspešne uložený",
|
||||
"timezone_mismatch_tooltip": "Prezeráte si správu na základe časového pásma vášho profilu ({{userTimezone}}), zatiaľ čo váš prehliadač je nastavený na časové pásmo ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Pridajte svoje nové reťazce nad túto líniu ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -67,4 +67,4 @@
|
||||
"reschedule_cta_short": "Preplánujte tu.",
|
||||
"you_and_conjunction": "Vy &",
|
||||
"email_survey_triggered_by_workflow": "Tento prieskum bol spustený pracovným postupom v Cal."
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Licencni ključ je uspešno sačuvan",
|
||||
"timezone_mismatch_tooltip": "Gledate izveštaj na osnovu vremenske zone vašeg profila ({{userTimezone}}), dok je vaš pretraživač podešen na vremensku zonu ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Dodajte svoje nove stringove iznad ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Licensnyckeln sparades framgångsrikt",
|
||||
"timezone_mismatch_tooltip": "Du tittar på rapporten baserat på din profiltidszon ({{userTimezone}}), medan din webbläsare är inställd på tidszonen ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -211,4 +211,4 @@
|
||||
"reschedule_cta_short": "இங்கே மீண்டும் ஷெடியூல் செய்யவும்.",
|
||||
"you_and_conjunction": "நீங்கள் &",
|
||||
"email_survey_triggered_by_workflow": "இந்த ஆய்வு Cal-ல் உள்ள பணிப்பாய்வு மூலம் தூண்டப்பட்டது."
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Lisans anahtarı başarıyla kaydedildi",
|
||||
"timezone_mismatch_tooltip": "Raporu profil saat diliminize ({{userTimezone}}) göre görüntülüyorsunuz, ancak tarayıcınız ({{browserTimezone}}) saat dilimine ayarlı",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni dizelerinizi yukarıya ekleyin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Ліцензійний ключ успішно збережено",
|
||||
"timezone_mismatch_tooltip": "Ви переглядаєте звіт на основі часового поясу вашого профілю ({{userTimezone}}), тоді як у вашому браузері встановлено часовий пояс ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "Đã lưu khóa giấy phép thành công",
|
||||
"timezone_mismatch_tooltip": "Bạn đang xem báo cáo dựa trên múi giờ hồ sơ của bạn ({{userTimezone}}), trong khi trình duyệt của bạn được đặt theo múi giờ ({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "许可证密钥已成功保存",
|
||||
"timezone_mismatch_tooltip": "您正在根据您的个人资料时区({{userTimezone}})查看报告,而您的浏览器设置为时区({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 在此上方添加您的新字符串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3360,4 +3360,4 @@
|
||||
"license_key_saved": "授權金鑰已成功儲存",
|
||||
"timezone_mismatch_tooltip": "您正在根據您的個人資料時區({{userTimezone}})查看報告,而您的瀏覽器設置為時區({{browserTimezone}})",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 請在此處新增您的字串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
import path from "path";
|
||||
|
||||
import { CALCOM_VERSION } from "@calcom/lib/constants";
|
||||
|
||||
function findMonorepoRoot(): string {
|
||||
let currentDir = __dirname;
|
||||
while (currentDir !== path.dirname(currentDir)) {
|
||||
try {
|
||||
const packageJsonPath = path.join(currentDir, "package.json");
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
||||
if (packageJson.workspaces && packageJson.name === "calcom-monorepo") {
|
||||
return currentDir;
|
||||
}
|
||||
} catch (error) {
|
||||
// package.json doesn't exist in this directory
|
||||
// Just continue to the next directory
|
||||
}
|
||||
currentDir = path.dirname(currentDir);
|
||||
}
|
||||
|
||||
throw new Error("Could not find monorepo root - repository structure may be corrupted");
|
||||
}
|
||||
|
||||
const LOCALES_PATH = path.join(findMonorepoRoot(), "packages/lib/server/locales");
|
||||
|
||||
interface LocaleCache {
|
||||
[cacheKey: string]: Record<string, string>;
|
||||
}
|
||||
|
||||
let localeCache: LocaleCache = {};
|
||||
let cacheVersion: string | null = null;
|
||||
|
||||
function loadTranslationForLocale(locale: string, ns: string): Record<string, string> {
|
||||
const cacheKey = `${locale}-${ns}-${CALCOM_VERSION}`;
|
||||
|
||||
if (cacheVersion === CALCOM_VERSION && localeCache[cacheKey]) {
|
||||
return localeCache[cacheKey];
|
||||
}
|
||||
|
||||
if (cacheVersion !== CALCOM_VERSION) {
|
||||
localeCache = {};
|
||||
cacheVersion = CALCOM_VERSION;
|
||||
}
|
||||
|
||||
try {
|
||||
const translationPath = join(LOCALES_PATH, locale, `${ns}.json`);
|
||||
const translations = JSON.parse(readFileSync(translationPath, "utf-8"));
|
||||
localeCache[cacheKey] = translations;
|
||||
return translations;
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load translations for ${locale}/${ns}:`, error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export function getBundledTranslations(locale: string, ns: string): Record<string, string> {
|
||||
const normalizedLocale = locale === "zh" ? "zh-CN" : locale;
|
||||
|
||||
const translations = loadTranslationForLocale(normalizedLocale, ns);
|
||||
if (Object.keys(translations).length > 0) {
|
||||
return translations;
|
||||
}
|
||||
|
||||
const englishTranslations = loadTranslationForLocale("en", ns);
|
||||
return englishTranslations;
|
||||
}
|
||||
@@ -3,14 +3,14 @@ import type { ReactNode } from "react";
|
||||
import { useState } from "react";
|
||||
import { useCallback } from "react";
|
||||
|
||||
import deTranslations from "@calcom/lib/server/locales/de/common.json";
|
||||
import enTranslations from "@calcom/lib/server/locales/en/common.json";
|
||||
import esTranslations from "@calcom/lib/server/locales/es/common.json";
|
||||
import frTranslations from "@calcom/lib/server/locales/fr/common.json";
|
||||
import nlTranslations from "@calcom/lib/server/locales/nl/common.json";
|
||||
import ptBrTranslations from "@calcom/lib/server/locales/pt-BR/common.json";
|
||||
import type { API_VERSIONS_ENUM } from "@calcom/platform-constants";
|
||||
import { IconSprites } from "@calcom/ui/components/icon";
|
||||
import deTranslations from "@calcom/web/public/static/locales/de/common.json";
|
||||
import enTranslations from "@calcom/web/public/static/locales/en/common.json";
|
||||
import esTranslations from "@calcom/web/public/static/locales/es/common.json";
|
||||
import frTranslations from "@calcom/web/public/static/locales/fr/common.json";
|
||||
import nlTranslations from "@calcom/web/public/static/locales/nl/common.json";
|
||||
import ptBrTranslations from "@calcom/web/public/static/locales/pt-BR/common.json";
|
||||
|
||||
import { AtomsContext } from "../hooks/useAtomsContext";
|
||||
import { useMe } from "../hooks/useMe";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type deTranslations from "@calcom/web/public/static/locales/de/common.json";
|
||||
import type enTranslations from "@calcom/web/public/static/locales/en/common.json";
|
||||
import type esTranslations from "@calcom/web/public/static/locales/es/common.json";
|
||||
import type frTranslations from "@calcom/web/public/static/locales/fr/common.json";
|
||||
import type nlTranslations from "@calcom/web/public/static/locales/nl/common.json";
|
||||
import type ptBrTranslations from "@calcom/web/public/static/locales/pt-BR/common.json";
|
||||
import type deTranslations from "@calcom/lib/server/locales/de/common.json";
|
||||
import type enTranslations from "@calcom/lib/server/locales/en/common.json";
|
||||
import type esTranslations from "@calcom/lib/server/locales/es/common.json";
|
||||
import type frTranslations from "@calcom/lib/server/locales/fr/common.json";
|
||||
import type nlTranslations from "@calcom/lib/server/locales/nl/common.json";
|
||||
import type ptBrTranslations from "@calcom/lib/server/locales/pt-BR/common.json";
|
||||
|
||||
export type enTranslationKeys = keyof typeof enTranslations;
|
||||
export type frTranslationKeys = keyof typeof frTranslations;
|
||||
|
||||
@@ -62,9 +62,9 @@ export default defineConfig(({ mode }) => {
|
||||
"@calcom/platform-constants": path.resolve(__dirname, "../constants/index.ts"),
|
||||
"@calcom/platform-types": path.resolve(__dirname, "../types/index.ts"),
|
||||
"@calcom/platform-utils": path.resolve(__dirname, "../constants/index.ts"),
|
||||
"@calcom/web/public/static/locales/en/common.json": path.resolve(
|
||||
"@calcom/lib/server/locales/en/common.json": path.resolve(
|
||||
__dirname,
|
||||
"../../../apps/web/public/static/locales/en/common.json"
|
||||
"../../lib/server/locales/en/common.json"
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -21704,6 +21704,7 @@ __metadata:
|
||||
prettier: ^2.8.6
|
||||
prismock: ^1.33.4
|
||||
resize-observer-polyfill: ^1.5.1
|
||||
ts-node: ^10.9.2
|
||||
tsc-absolute: ^1.0.0
|
||||
turbo: ^1.10.1
|
||||
typescript: ^5.7.2
|
||||
@@ -44895,6 +44896,44 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-node@npm:^10.9.2":
|
||||
version: 10.9.2
|
||||
resolution: "ts-node@npm:10.9.2"
|
||||
dependencies:
|
||||
"@cspotcode/source-map-support": ^0.8.0
|
||||
"@tsconfig/node10": ^1.0.7
|
||||
"@tsconfig/node12": ^1.0.7
|
||||
"@tsconfig/node14": ^1.0.0
|
||||
"@tsconfig/node16": ^1.0.2
|
||||
acorn: ^8.4.1
|
||||
acorn-walk: ^8.1.1
|
||||
arg: ^4.1.0
|
||||
create-require: ^1.1.0
|
||||
diff: ^4.0.1
|
||||
make-error: ^1.1.1
|
||||
v8-compile-cache-lib: ^3.0.1
|
||||
yn: 3.1.1
|
||||
peerDependencies:
|
||||
"@swc/core": ">=1.2.50"
|
||||
"@swc/wasm": ">=1.2.50"
|
||||
"@types/node": "*"
|
||||
typescript: ">=2.7"
|
||||
peerDependenciesMeta:
|
||||
"@swc/core":
|
||||
optional: true
|
||||
"@swc/wasm":
|
||||
optional: true
|
||||
bin:
|
||||
ts-node: dist/bin.js
|
||||
ts-node-cwd: dist/bin-cwd.js
|
||||
ts-node-esm: dist/bin-esm.js
|
||||
ts-node-script: dist/bin-script.js
|
||||
ts-node-transpile-only: dist/bin-transpile.js
|
||||
ts-script: dist/bin-script-deprecated.js
|
||||
checksum: fde256c9073969e234526e2cfead42591b9a2aec5222bac154b0de2fa9e4ceb30efcd717ee8bc785a56f3a119bdd5aa27b333d9dbec94ed254bd26f8944c67ac
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-pattern@npm:4.3.0":
|
||||
version: 4.3.0
|
||||
resolution: "ts-pattern@npm:4.3.0"
|
||||
|
||||
Reference in New Issue
Block a user