Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bbb748d
refactor: replace i18n HTTP requests with build-time bundling
devin-ai-integration[bot] Jul 11, 2025
2cf8627
fix: move i18n files back to packages/lib/server with proper imports
devin-ai-integration[bot] Jul 11, 2025
6169425
refactor: move locale files to packages/lib/server to eliminate circu…
devin-ai-integration[bot] Jul 11, 2025
a71390a
fix: update test imports after locale refactor
devin-ai-integration[bot] Jul 11, 2025
c9be2b3
fix: revert import paths from @calcom/web/lib/i18n to @calcom/lib/ser…
devin-ai-integration[bot] Jul 11, 2025
079c5b8
fix: update vite config alias to use new locale path
devin-ai-integration[bot] Jul 11, 2025
ca91e04
fix: update translationBundler path resolution for production builds
devin-ai-integration[bot] Jul 11, 2025
43351a8
fix: use relative path resolution for locale files in translationBundler
devin-ai-integration[bot] Jul 11, 2025
30db53d
fix: use process.cwd() for locale path resolution in production builds
devin-ai-integration[bot] Jul 11, 2025
607556a
fix: use path.resolve pattern from sendVerificationRequest for locale…
devin-ai-integration[bot] Jul 11, 2025
df95949
fix: use dynamic monorepo root detection for locale path resolution
devin-ai-integration[bot] Jul 11, 2025
b37d822
fix: use require.resolve(__filename) for robust path resolution in al…
devin-ai-integration[bot] Jul 11, 2025
8bf95f9
Revert "fix: use require.resolve(__filename) for robust path resoluti…
devin-ai-integration[bot] Jul 11, 2025
c6c493e
fix: update copied locale files after translationBundler path resolut…
devin-ai-integration[bot] Jul 11, 2025
4c38246
feat: remove existing locale files to establish copy script as single…
devin-ai-integration[bot] Jul 12, 2025
37b866a
add comment
hbjORbj Jul 12, 2025
bcf2416
refactor: simplify findMonorepoRoot by removing redundant fallback loop
devin-ai-integration[bot] Jul 12, 2025
1dbb21a
Merge branch 'devin/1752247164-refactor-i18n-build-time-bundling' of …
devin-ai-integration[bot] Jul 12, 2025
ce6ca79
Merge branch 'main' of https://git-manager.devin.ai/proxy/github.com/…
devin-ai-integration[bot] Jul 12, 2025
2b9ecae
feat: integrate updated translations from main branch
devin-ai-integration[bot] Jul 12, 2025
5ce88dd
chore: update package.json and yarn.lock after translation integration
devin-ai-integration[bot] Jul 12, 2025
ce13c3d
feat: remove duplicate locale files from apps/web to establish single…
devin-ai-integration[bot] Jul 12, 2025
c1e0018
Merge branch 'main' into devin/1752247164-refactor-i18n-build-time-bu…
keithwillcode Jul 12, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
2 changes: 1 addition & 1 deletion apps/api/v2/next-i18next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/next.config.js
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/playwright/lib/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
2 changes: 1 addition & 1 deletion apps/web/scripts/check-missing-translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
25 changes: 25 additions & 0 deletions apps/web/scripts/copy-locales-static.js
Original file line number Diff line number Diff line change
@@ -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();
2 changes: 1 addition & 1 deletion i18n-unused.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: ":",
Expand Down
2 changes: 1 addition & 1 deletion i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/buildCalEventFromBooking.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
39 changes: 17 additions & 22 deletions packages/lib/server/i18n.ts
Original file line number Diff line number Diff line change
@@ -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>();
Expand All @@ -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 {};
}
}
Expand All @@ -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) {
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3360,4 +3360,4 @@
"license_key_saved": "تم حفظ مفتاح الترخيص بنجاح",
"timezone_mismatch_tooltip": "أنت تشاهد التقرير بناءً على المنطقة الزمنية لملفك الشخصي ({{userTimezone}})، بينما متصفحك مضبوط على المنطقة الزمنية ({{browserTimezone}})",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ أضف السلاسل الجديدة أعلاه هنا ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3360,4 +3360,4 @@
"license_key_saved": "Лицензионният ключ е успешно записан",
"timezone_mismatch_tooltip": "Преглеждате отчета според часовата зона на вашия профил ({{userTimezone}}), докато браузърът ви е настроен на часова зона ({{browserTimezone}})",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Добавете новите си низове над този ред ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3360,4 +3360,4 @@
"license_key_saved": "লাইসেন্স কী সফলভাবে সংরক্ষিত হয়েছে",
"timezone_mismatch_tooltip": "আপনি আপনার প্রোফাইল টাইমজোন ({{userTimezone}}) অনুসারে রিপোর্ট দেখছেন, যখন আপনার ব্রাউজার টাইমজোন ({{browserTimezone}}) এ সেট করা আছে",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑ুষান্ত"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3360,4 +3360,4 @@
"license_key_saved": "Το κλειδί άδειας αποθηκεύτηκε με επιτυχία",
"timezone_mismatch_tooltip": "Βλέπετε την αναφορά με βάση τη ζώνη ώρας του προφίλ σας ({{userTimezone}}), ενώ ο περιηγητής σας είναι ρυθμισμένος στη ζώνη ώρας ({{browserTimezone}})",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Προσθέστε τις νέες συμβολοσειρές σας πάνω από εδώ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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."
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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."
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3360,4 +3360,4 @@
"license_key_saved": "ライセンスキーが正常に保存されました",
"timezone_mismatch_tooltip": "あなたはプロフィールのタイムゾーン({{userTimezone}})に基づいてレポートを表示していますが、ブラウザのタイムゾーンは({{browserTimezone}})に設定されています",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ この上に新しい文字列を追加してください ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
Loading
Loading