@@ -20,6 +20,20 @@ function* walk(dir) {
2020 }
2121}
2222
23+ /**
24+ * Fallback to get start/end indices of a key within a line.
25+ * @param {string } line - Line of text to search in.
26+ * @param {string } key - Key to find.
27+ * @returns {[number, number] } Array [start, end] representing the indices of the key in the line.
28+ */
29+ function getStartEnd ( line , key ) {
30+ let start = line . indexOf ( key ) ;
31+ if ( start === - 1 ) {
32+ start = 0 ;
33+ }
34+ return [ start , start + key . length ] ;
35+ }
36+
2337describe ( "Check Translations" , ( ) => {
2438 it ( "should not have missing translation keys" , ( ) => {
2539 const enTranslations = JSON . parse ( fs . readFileSync ( "src/lang/en.json" , "utf-8" ) ) ;
@@ -28,28 +42,53 @@ describe("Check Translations", () => {
2842 /// this check is just to save on maintainer energy to explain this on every review ^^
2943 const translationRegex = / \$ t \( [ ' " ] (?< key1 > .* ?) [ ' " ] \s * [ , ) ] | i 1 8 n - t [ ^ > ] * \s + k e y p a t h = " (?< key2 > [ ^ " ] + ) " / gd;
3044
45+ // detect server-side TranslatableError usage: new TranslatableError("key")
46+ const translatableErrorRegex = / n e w \s + T r a n s l a t a b l e E r r o r \( \s * [ ' " ] (?< key3 > [ ^ ' " ] + ) [ ' " ] \s * \) / g;
47+
3148 const missingKeys = [ ] ;
3249
33- for ( const filePath of walk ( "src" ) ) {
34- if ( filePath . endsWith ( ".vue" ) || filePath . endsWith ( ".js" ) ) {
35- const lines = fs . readFileSync ( filePath , "utf-8" ) . split ( "\n" ) ;
36- lines . forEach ( ( line , lineNum ) => {
37- let match ;
38- while ( ( match = translationRegex . exec ( line ) ) !== null ) {
39- const key = match . groups . key1 || match . groups . key2 ;
40- if ( key && ! enTranslations [ key ] ) {
41- const [ start , end ] = match . groups . key1 ? match . indices . groups . key1 : match . indices . groups . key2 ;
42- missingKeys . push ( {
43- filePath,
44- lineNum : lineNum + 1 ,
45- key,
46- line : line ,
47- start,
48- end,
49- } ) ;
50+ const roots = [ "src" , "server" ] ;
51+
52+ for ( const root of roots ) {
53+ for ( const filePath of walk ( root ) ) {
54+ if ( filePath . endsWith ( ".vue" ) || filePath . endsWith ( ".js" ) ) {
55+ const lines = fs . readFileSync ( filePath , "utf-8" ) . split ( "\n" ) ;
56+ lines . forEach ( ( line , lineNum ) => {
57+ let match ;
58+ // front-end style keys ($t / i18n-t)
59+ while ( ( match = translationRegex . exec ( line ) ) !== null ) {
60+ const key = match . groups . key1 || match . groups . key2 ;
61+ if ( key && ! enTranslations [ key ] ) {
62+ const [ start , end ] = getStartEnd ( line , key ) ;
63+ missingKeys . push ( {
64+ filePath,
65+ lineNum : lineNum + 1 ,
66+ key,
67+ line : line ,
68+ start,
69+ end,
70+ } ) ;
71+ }
72+ }
73+
74+ // server-side TranslatableError usage
75+ let m ;
76+ while ( ( m = translatableErrorRegex . exec ( line ) ) !== null ) {
77+ const key3 = m . groups . key3 ;
78+ if ( key3 && ! enTranslations [ key3 ] ) {
79+ const [ start , end ] = getStartEnd ( line , key3 ) ;
80+ missingKeys . push ( {
81+ filePath,
82+ lineNum : lineNum + 1 ,
83+ key : key3 ,
84+ line : line ,
85+ start,
86+ end,
87+ } ) ;
88+ }
5089 }
51- }
52- } ) ;
90+ } ) ;
91+ }
5392 }
5493 }
5594
0 commit comments