Skip to content

Commit 2a8d30f

Browse files
committed
feat: overrides fo translation
1 parent 68716c1 commit 2a8d30f

9 files changed

Lines changed: 1000 additions & 79 deletions

File tree

cmp/compiler/src/plugin/transform/__snapshots__/transform.test.ts.snap

Lines changed: 185 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ import Image from "next/image";
463463
export default function Button() {
464464
const {
465465
t
466-
} = useTranslation(["0fab30e30c5b", "fca9b3359e5e"]);
466+
} = useTranslation(["fca9b3359e5e", "0fab30e30c5b"]);
467467
return <a href="/deploy">
468468
<Image src="/icon.svg" alt={t("0fab30e30c5b", "Icon")} width={16} height={16} />{t("fca9b3359e5e", "Deploy Now")}</a>;
469469
}"
@@ -811,6 +811,190 @@ export function Example() {
811811
}"
812812
`;
813813
814+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle brand names and technical terms 1`] = `
815+
"import { useTranslation } from "@lingo.dev/compiler/react";
816+
export function Header() {
817+
const {
818+
t
819+
} = useTranslation(["16731724003e", "03eb567568a5"]);
820+
return <div>
821+
<h1>{t("16731724003e", "Lingo.dev")}</h1>
822+
<p>{t("03eb567568a5", "JWT token is invalid")}</p>
823+
</div>;
824+
}"
825+
`;
826+
827+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle multiple elements with different overrides 1`] = `
828+
"import { useTranslation } from "@lingo.dev/compiler/react";
829+
export function Page() {
830+
const {
831+
t
832+
} = useTranslation(["2c49fa19d1b8", "3d33e41209ee", "38ee9c3017d4"]);
833+
return <div>
834+
<h1>{t("2c49fa19d1b8", "Title")}</h1>
835+
<p>{t("3d33e41209ee", "Description")}</p>
836+
<button>{t("38ee9c3017d4", "Click")}</button>
837+
</div>;
838+
}"
839+
`;
840+
841+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle override alongside other attributes 1`] = `
842+
"import { useTranslation } from "@lingo.dev/compiler/react";
843+
export function Button() {
844+
const {
845+
t
846+
} = useTranslation(["0be1d46bd3b7"]);
847+
return <button className="primary" onClick={handleClick} disabled={false}>{t("0be1d46bd3b7", "Submit")}</button>;
848+
}"
849+
`;
850+
851+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle overrides in mixed content (rich text) 1`] = `
852+
"import { useTranslation } from "@lingo.dev/compiler/react";
853+
export function Message() {
854+
const {
855+
t
856+
} = useTranslation(["d81c47e737e1"]);
857+
const name = "Alice";
858+
return <div>{t("d81c47e737e1", "Welcome {name}, you have <strong0>{count}</strong0> messages", {
859+
name,
860+
count,
861+
strong0: chunks => <strong>{chunks}</strong>
862+
})}</div>;
863+
}"
864+
`;
865+
866+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle overrides in non-async server components with unified hook 1`] = `
867+
"import { useTranslation } from "@lingo.dev/compiler/react";
868+
export default function ServerPage() {
869+
const {
870+
t
871+
} = useTranslation(["5d97e151703a", "57b5dc21ee4c"]);
872+
return <div>
873+
<h1>{t("5d97e151703a", "Welcome")}</h1>
874+
<p>{t("57b5dc21ee4c", "Description")}</p>
875+
</div>;
876+
}"
877+
`;
878+
879+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle overrides in server components with async 1`] = `
880+
"import { getServerTranslations } from "@lingo.dev/compiler/react/server";
881+
export default async function ServerPage() {
882+
const {
883+
t
884+
} = await getServerTranslations({
885+
hashes: ["5d97e151703a", "9598a4aa5fff"]
886+
});
887+
const data = await fetchData();
888+
return <div>
889+
<h1>{t("5d97e151703a", "Welcome")}</h1>
890+
<p>{t("9598a4aa5fff", "Data: {data}", {
891+
data
892+
})}</p>
893+
</div>;
894+
}"
895+
`;
896+
897+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle overrides with locale region codes 1`] = `
898+
"import { useTranslation } from "@lingo.dev/compiler/react";
899+
export function Welcome() {
900+
const {
901+
t
902+
} = useTranslation(["1f0e8650e31f"]);
903+
return <h1>{t("1f0e8650e31f", "Welcome")}</h1>;
904+
}"
905+
`;
906+
907+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle overrides with special characters 1`] = `
908+
"import { useTranslation } from "@lingo.dev/compiler/react";
909+
export function Legal() {
910+
const {
911+
t
912+
} = useTranslation(["718271d78b60"]);
913+
return <p>{t("718271d78b60", "In accordance with GDPR Article 15...")}</p>;
914+
}"
915+
`;
916+
917+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle partial overrides (only some locales) 1`] = `
918+
"import { useTranslation } from "@lingo.dev/compiler/react";
919+
export function Message() {
920+
const {
921+
t
922+
} = useTranslation(["a97a23bf9109"]);
923+
return <p>{t("a97a23bf9109", "Special text")}</p>;
924+
}"
925+
`;
926+
927+
exports[`transformComponent > translation overrides (data-lingo-override) > should handle template literals in override values 1`] = `
928+
"import { useTranslation } from "@lingo.dev/compiler/react";
929+
export function Message() {
930+
const {
931+
t
932+
} = useTranslation(["20a45a35c47e"]);
933+
return <p>{t("20a45a35c47e", "Message")}</p>;
934+
}"
935+
`;
936+
937+
exports[`transformComponent > translation overrides (data-lingo-override) > should not add overrides field when override is empty object 1`] = `
938+
"import { useTranslation } from "@lingo.dev/compiler/react";
939+
export function Button() {
940+
const {
941+
t
942+
} = useTranslation(["43e1aff00fc2"]);
943+
return <button data-lingo-override={{}}>{t("43e1aff00fc2", "Click")}</button>;
944+
}"
945+
`;
946+
947+
exports[`transformComponent > translation overrides (data-lingo-override) > should not add overrides field when override is invalid 1`] = `
948+
"import { useTranslation } from "@lingo.dev/compiler/react";
949+
export function Button() {
950+
const {
951+
t
952+
} = useTranslation(["43e1aff00fc2"]);
953+
return <button data-lingo-override={null}>{t("43e1aff00fc2", "Click")}</button>;
954+
}"
955+
`;
956+
957+
exports[`transformComponent > translation overrides (data-lingo-override) > should not apply overrides to elements without translatable content 1`] = `
958+
"export function Empty() {
959+
return <div data-lingo-override={{
960+
de: "Text"
961+
}}></div>;
962+
}"
963+
`;
964+
965+
exports[`transformComponent > translation overrides (data-lingo-override) > should parse override attribute with JSON string 1`] = `
966+
"import { useTranslation } from "@lingo.dev/compiler/react";
967+
export function Button() {
968+
const {
969+
t
970+
} = useTranslation(["43e1aff00fc2"]);
971+
return <button>{t("43e1aff00fc2", "Click")}</button>;
972+
}"
973+
`;
974+
975+
exports[`transformComponent > translation overrides (data-lingo-override) > should parse override attribute with object expression 1`] = `
976+
"import { useTranslation } from "@lingo.dev/compiler/react";
977+
export function Button() {
978+
const {
979+
t
980+
} = useTranslation(["b8ee597b5d56"]);
981+
return <button>{t("b8ee597b5d56", "Click here")}</button>;
982+
}"
983+
`;
984+
985+
exports[`transformComponent > translation overrides (data-lingo-override) > should validate locale codes and reject invalid ones 1`] = `
986+
"import { useTranslation } from "@lingo.dev/compiler/react";
987+
export function Button() {
988+
const {
989+
t
990+
} = useTranslation(["43e1aff00fc2"]);
991+
return <button data-lingo-override={{
992+
german: "Klicken",
993+
"en_US": "Click"
994+
}}>{t("43e1aff00fc2", "Click")}</button>;
995+
}"
996+
`;
997+
814998
exports[`transformComponent > use directive mode > should transform files with 'use i18n' directive 1`] = `
815999
""use i18n";
8161000

cmp/compiler/src/plugin/transform/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export function transformComponent({
7777
transformed: translationEntries.length > 0,
7878
};
7979
} catch (error) {
80+
// TODO (AleksandrSl 08/12/2025): Should also log the message
8081
logger.error(`Failed to transform ${filePath}:`, error);
8182
// Return original code on error
8283
return {

0 commit comments

Comments
 (0)