Šķîþ ţö ḿàîñ çöñţéñţ

ĴàṽàŠçŕîþţ Šçŕîþţ Šţéþ

Ţĥé šçŕîþţ šţéþ ļéţš ýöü ŕüñ çüšţöḿ ĴàṽàŠçŕîþţ (ÉŠ5) öñ éàçĥ Þàŕţ ƒļöŵîñĝ ţĥŕöüĝĥ ţĥé þîþéļîñé. Îţ üšéš ţĥé ĝöĵà ÉŠ5 ŕüñţîḿé -- à þüŕé Ĝö ĴàṽàŠçŕîþţ éñĝîñé ŵîţĥ ñö ÇĜö đéþéñđéñçý.

Ĥöŵ îţ ŵöŕķš

Ţĥé šçŕîþţ ţööļ ŕéçéîṽéš éàçĥ Þàŕţ öñé àţ à ţîḿé. Ƒöŕ éàçĥ Þàŕţ, ýöüŕ šçŕîþţ ŕüñš ŵîţĥ àççéšš ţö à part öƃĵéçţ àñđ ţĥŕéé çöñţŕöļ ƒüñçţîöñš: emit(), skip(), àñđ log(). ΃ ýöüŕ šçŕîþţ çàļļš ñéîţĥéŕ emit() ñöŕ skip(), ţĥé Þàŕţ þàššéš ţĥŕöüĝĥ üñçĥàñĝéđ.

Ýöü çàñ ŵŕîţé ýöüŕ ļöĝîç îñ éîţĥéŕ öƒ ţŵö éǫüîṽàļéñţ ƒöŕḿš: àš ţöþ-ļéṽéļ çöđé àĝàîñšţ ţĥé îḿþļîçîţ part ĝļöƃàļ (üšéđ ţĥŕöüĝĥöüţ ţĥé éẋàḿþļéš ƃéļöŵ), öŕ àš à function process(part) ţĥàţ ţĥé ţööļ çàļļš öñçé þéŕ Þàŕţ (šéé Ƒüñçţîöñ ƒöŕḿ). Ƃöţĥ ĥàṽé îđéñţîçàļ çàþàƃîļîţîéš; ţĥé ƒüñçţîöñ ƒöŕḿ àđđš à ŕéţüŕñ-ṽàļüé çöñṽéñîéñçé.

Ţĥé ĴàṽàŠçŕîþţ ÀÞÎ

Ţĥé þàŕţ öƃĵéçţ

part.type; // "block", "data", "media", "layer-start", "layer-end",
// "group-start", "group-end"

Ƒöŕ ƃļöçķ þàŕţš, ţĥé block þŕöþéŕţý þŕöṽîđéš àççéšš ţö ţŕàñšļàţàƃļé çöñţéñţ:

part.block.id; // Block ID string
part.block.translatable; // boolean

// Source runs (flat array)
part.block.source[0].content.text; // text of the first run

// Target runs by locale (object)
part.block.targets["fr"][0].content.text; // French target's first run text

éḿîţ(þàŕţ)

Éḿîţ à ḿöđîƒîéđ (öŕ ñéŵ) Þàŕţ ţö ţĥé öüţþüţ çĥàññéļ. ΃ ýöü çàļļ emit(), ţĥé öŕîĝîñàļ Þàŕţ îš ñöţ ƒöŕŵàŕđéđ àüţöḿàţîçàļļý -- öñļý ŵĥàţ ýöü éḿîţ ŕéàçĥéš đöŵñšţŕéàḿ ţööļš.

// Modify a target translation and emit
if (part.block.targets["fr"]) {
var seg = part.block.targets["fr"][0];
seg.content.text = seg.content.text.toUpperCase();
}
emit(part);

Ƃý đéƒàüļţ ţĥé šçŕîþţ ḿàý ŕéàđ ţĥé šöüŕçé ƃüţ öñļý ţàŕĝéţ éđîţš àŕé ŕéàđ ƃàçķ, ƃéçàüšé ţĥé šöüŕçé îš ŕéàđ-öñļý (šéé Çöñƒîĝüŕàţîöñ ŕéƒéŕéñçé).

šķîþ()

Đŕöþ ţĥé çüŕŕéñţ Þàŕţ éñţîŕéļý. Îţ ŵîļļ ñöţ ŕéàçĥ đöŵñšţŕéàḿ ţööļš öŕ ţĥé ŵŕîţéŕ.

if (part.type === "block" && part.block.source[0].content.text === "") {
skip();
}

ļöĝ(ḿéššàĝé)

Ŵŕîţé à ḿéššàĝé ţö šţđéŕŕ ƒöŕ đéƃüĝĝîñĝ.

log("Processing block: " + part.block.id);

Çöñţŕöļ ƒļöŵ šüḿḿàŕý

Šçŕîþţ ƃéĥàṽîöŕŔéšüļţ
Ñö emit() öŕ skip() çàļļéđÞàŕţ þàššéš ţĥŕöüĝĥ üñçĥàñĝéđ
emit(part) çàļļéđÖñļý éḿîţţéđ þàŕţš àŕé ƒöŕŵàŕđéđ
skip() çàļļéđÞàŕţ îš đŕöþþéđ
emit() çàļļéđ ḿüļţîþļé ţîḿéšÀļļ éḿîţţéđ þàŕţš àŕé ƒöŕŵàŕđéđ (öñé-ţö-ḿàñý)

Ƒüñçţîöñ ƒöŕḿ

Îñšţéàđ öƒ ŵŕîţîñĝ ţöþ-ļéṽéļ çöđé àĝàîñšţ ţĥé îḿþļîçîţ part ĝļöƃàļ, ýöü çàñ đéƒîñé à process ƒüñçţîöñ. Ţĥé ţööļ çàļļš îţ öñçé þéŕ Þàŕţ, þàššîñĝ ţĥé þàŕţ àš îţš àŕĝüḿéñţ:

function process(part) {
if (part.type === "block" && part.block.targets["fr"]) {
var seg = part.block.targets["fr"][0];
seg.content.text = seg.content.text.toUpperCase();
}
return part; // emit the (modified) part
}

Îñšîđé process, emit(), skip(), àñđ log() ƃéĥàṽé éẋàçţļý àš îñ ţĥé îḿþļîçîţ-ĝļöƃàļš ƒöŕḿ. Àš à çöñṽéñîéñçé, ţĥé ƒüñçţîöñ'š ŕéţüŕñ ṽàļüé îš àļšö ĥöñöŕéđ, ƃüţ öñļý ŵĥéñ ýöü ĥàṽé ñöţ àļŕéàđý çàļļéđ emit() öŕ skip() (àñ éẋþļîçîţ çàļļ àļŵàýš ŵîñš):

process(part) ŕéţüŕñšŔéšüļţ
à þàŕţ öƃĵéçţţĥàţ þàŕţ îš éḿîţţéđ
àñ àŕŕàý öƒ þàŕţšàļļ àŕé éḿîţţéđ (öñé-ţö-ḿàñý)
nullţĥé þàŕţ îš đŕöþþéđ (éǫüîṽàļéñţ ţö skip())
ñöţĥîñĝ (undefined)ţĥé þàŕţ þàššéš ţĥŕöüĝĥ üñçĥàñĝéđ

Ţĥé ƒüñçţîöñ ƒöŕḿ ŵöŕķš îđéñţîçàļļý ŵîţĥ --code, --script-file, àñđ ţĥé ÝÀḾĻ code/scriptFile çöñƒîĝ. Îţ ŕéàđš ñàţüŕàļļý ƒöŕ ţŕàñšƒöŕḿš ţĥàţ çöḿþüţé àñđ ŕéţüŕñ à ŕéšüļţ; ţĥé îḿþļîçîţ-ĝļöƃàļš ƒöŕḿ îš ţéŕšéŕ ƒöŕ šîḿþļé ƒîļţéŕš. Šöüŕçé éđîţš šţîļļ ŕéǫüîŕé allowSourceMutation (šéé Çöñƒîĝüŕàţîöñ ŕéƒéŕéñçé) îñ éîţĥéŕ ƒöŕḿ.

ÇĻÎ üšàĝé

Îñļîñé çöđé

kapi exec script -i input.xliff --code 'if (part.type === "block") {
var text = part.block.source[0].content.text;
if (text.length > 100) { skip(); }
}'

Šçŕîþţ ƒîļé

kapi exec script -i input.xliff --script-file filter.js

Ŵĥéŕé filter.js çöñţàîñš:

if (part.type === "block") {
var text = part.block.source[0].content.text;
if (text.length <= 5) {
skip();
}
}

ÝÀḾĻ ƒļöŵ üšàĝé

Üšé ţĥé šçŕîþţ šţéþ îñļîñé îñ à ƒļöŵ đéƒîñîţîöñ:

steps:
- tool: script
label: Filter short segments
config:
code: |
if (part.type === 'block') {
var text = part.block.source[0].content.text;
if (text.length < 3) {
skip();
}
}

- tool: pseudo-translate
config:
targetLocale: fr

Öŕ ŕéƒéŕéñçé àñ éẋţéŕñàļ ƒîļé:

steps:
- tool: script
config:
scriptFile: ./scripts/filter.js

- tool: pseudo-translate
config:
targetLocale: fr

Éẋàḿþļéš

Ƒîļţéŕ ƃý šöüŕçé ţéẋţ ļéñĝţĥ

Šķîþ ƃļöçķš ŵĥéŕé ţĥé šöüŕçé ţéẋţ îš šĥöŕţéŕ ţĥàñ à ţĥŕéšĥöļđ:

if (part.type === "block") {
var text = part.block.source[0].content.text;
if (text.length < 10) {
skip();
}
}

Ḿöđîƒý ţàŕĝéţ ţéẋţ

Àþþéñđ à ḿàŕķéŕ ţö àļļ Ƒŕéñçĥ ţŕàñšļàţîöñš:

if (part.type === "block" && part.block.targets["fr"]) {
var seg = part.block.targets["fr"][0];
seg.content.text = seg.content.text + " [REVIEW]";
emit(part);
}

Çöñđîţîöñàļ ŕöüţîñĝ

Öñļý þàšš ţŕàñšļàţàƃļé ƃļöçķš ţĥŕöüĝĥ ţö đöŵñšţŕéàḿ ţööļš:

if (part.type !== "block") {
// Let structural parts (layers, data) pass through
emit(part);
} else if (part.block.translatable) {
emit(part);
} else {
skip();
}

Ţŕàñšƒöŕḿ šöüŕçé ţéẋţ

Ñöŕḿàļîžé ŵĥîţéšþàçé îñ ţĥé šöüŕçé ƃéƒöŕé ţŕàñšļàţîöñ. Šöüŕçé éđîţš àŕé îĝñöŕéđ ƃý đéƒàüļţ, ƃéçàüšé ţĥé šöüŕçé îš ŕéàđ-öñļý ţö ţĥé šçŕîþţ (îḿḿüţàƃîļîţý çöñţŕàçţ). Öþţ îñ ŵîţĥ allowSourceMutation: true, àñđ þļàçé ţĥé šţéþ àĥéàđ öƒ ţĥé šţéþš ţĥàţ šĥöüļđ öƃšéŕṽé ţĥé ŕéŵŕîţţéñ šöüŕçé, ţýþîçàļļý ƒîŕšţ (šéé ƒļöŵ àüţĥöŕîñĝ):

steps:
- tool: script
config:
allowSourceMutation: true
code: |
if (part.type === 'block') {
var text = part.block.source[0].content.text;
text = text.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '');
part.block.source[0].content.text = text;
emit(part);
}
- tool: translate

Ļöĝ àñđ þàšš ţĥŕöüĝĥ

Îñšþéçţ ţĥé þîþéļîñé ŵîţĥöüţ çĥàñĝîñĝ àñýţĥîñĝ:

if (part.type === "block") {
log("Block " + part.block.id + ": " + part.block.source[0].content.text);
}
// No emit() or skip() -- part passes through unchanged

Çöñƒîĝüŕàţîöñ ŕéƒéŕéñçé

ÞŕöþéŕţýŢýþéĐéšçŕîþţîöñ
sourcešţŕîñĝḾöđé šéļéçţöŕ: inline (đéƒàüļţ) öŕ file
codešţŕîñĝÎñļîñé ĴàṽàŠçŕîþţ çöđé (ÉŠ5)
scriptFilešţŕîñĝÞàţĥ ţö à .js ƒîļé
allowSourceMutationƃööļéàñÞéŕḿîţ ţĥé šçŕîþţ ţö ḿöđîƒý ţĥé šöüŕçé ţéẋţ. Öƒƒ ƃý đéƒàüļţ: ţĥé šöüŕçé îš ŕéàđ-öñļý àñđ šöüŕçé éđîţš àŕé îĝñöŕéđ üñļéšš ţĥîš îš šéţ.

Þŕöṽîđé éîţĥéŕ code öŕ scriptFile. Ţĥé öþţîöñàļ source ƒîéļđ šéļéçţš ţĥé ḿöđé éẋþļîçîţļý (inline öŕ file) ƒöŕ ÜÎ àñđ ṽàļîđàţîöñ; ŵĥéñ öḿîţţéđ, ţĥé ḿöđé îš îñƒéŕŕéđ ƒŕöḿ ŵĥîçĥéṽéŕ öƒ code/scriptFile îš šéţ.

Ñöţéš

  • Ţĥé ŕüñţîḿé îš ÉŠ5 öñļý (ñö let, const, àŕŕöŵ ƒüñçţîöñš, öŕ ţéḿþļàţé ļîţéŕàļš). Üšé var ƒöŕ ṽàŕîàƃļé đéçļàŕàţîöñš.
  • Éàçĥ ţööļ îñšţàñçé ĝéţš îţš öŵñ ĝöĵà ŕüñţîḿé, šö ţĥéŕé îš ñö šĥàŕéđ šţàţé ƃéţŵééñ þàŕàļļéļ þîþéļîñé ƃŕàñçĥéš.
  • Ţĥé šçŕîþţ ŕüñš šýñçĥŕöñöüšļý ƒöŕ éàçĥ Þàŕţ. Ļöñĝ-ŕüññîñĝ šçŕîþţš ŵîļļ ƃļöçķ ţĥé þîþéļîñé.
  • Ţàŕĝéţ ţéẋţ éđîţš öñ ƃļöçķ þàŕţš àŕé ŕéàđ ƃàçķ. Šöüŕçé éđîţš àŕé ŕéàđ ƃàçķ öñļý ŵĥéñ allowSourceMutation: true; öţĥéŕŵîšé ţĥé šöüŕçé îš ŕéàđ-öñļý. Çĥàñĝéš ţö öţĥéŕ Þàŕţ ţýþéš àŕé ñöţ þéŕšîšţéđ.