diff --git a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts
index 1d19cdd4d0..d5b999ddee 100644
--- a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts
+++ b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts
@@ -291,7 +291,7 @@ export class Vars extends Section {
});
}
findStringVariableValue(id: string): string {
- return Vars.findVariable(this.strings, id)?.value?.value; // Unwrap: Variable, StrsItem
+ return Vars.findVariable(this.strings, id)?.value?.value ?? null; // Unwrap: Variable, StrsItem
}
substituteSetRegex(str: string, sections: DependencySections): string {
return str.replaceAll(VariableParser.SET_REFERENCE, (_entire, id) => {
diff --git a/developer/src/kmc-ldml/src/compiler/vars.ts b/developer/src/kmc-ldml/src/compiler/vars.ts
index fb9b2f7596..39bc9304af 100644
--- a/developer/src/kmc-ldml/src/compiler/vars.ts
+++ b/developer/src/kmc-ldml/src/compiler/vars.ts
@@ -68,9 +68,16 @@ export class VarsCompiler extends SectionCompiler {
// Strings
for (const { id, value } of variables.string) {
addId(id);
- allStrings.add(id);
const stringrefs = VariableParser.allStringReferences(value);
+ for(const ref of stringrefs) {
+ if(!allStrings.has(ref)) {
+ valid = false;
+ this.callbacks.reportMessage(LdmlCompilerMessages.Error_MissingStringVariable({id: ref}));
+ allStrings.add(ref); // avoids multiple reports of same missing variable
+ }
+ }
st.string.add(SubstitutionUse.variable, stringrefs);
+ allStrings.add(id);
}
// Sets
for (const { id, value } of variables.set) {
diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml
new file mode 100644
index 0000000000..25e7c46a1d
--- /dev/null
+++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/developer/src/kmc-ldml/test/test-vars.ts b/developer/src/kmc-ldml/test/test-vars.ts
index 42b5d7df80..d513574ee8 100644
--- a/developer/src/kmc-ldml/test/test-vars.ts
+++ b/developer/src/kmc-ldml/test/test-vars.ts
@@ -187,7 +187,14 @@ describe('vars', function () {
LdmlCompilerMessages.Error_MissingStringVariable({id: 'missingStringInSet'})
],
},
- ], varsDependencies);
+ {
+ subpath: 'sections/vars/fail-badref-7.xml',
+ errors: [
+ LdmlCompilerMessages.Error_MissingStringVariable({id: 'usedBeforeDefinition'})
+ ],
+ strictErrors: true
+ },
+], varsDependencies);
describe('should match some marker constants', () => {
// neither of these live here, but, common/web/types does not import ldml-keyboard-constants otherwise.
diff --git a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts
index 5435e32286..8cf2234fd3 100644
--- a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts
+++ b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts
@@ -153,7 +153,7 @@ describe('visual-keyboard-compiler', function() {
assert.equal(vk.keys[1].text, '\u{0e81}');
});
- it.skip('should read string variables in key.output', async function() {
+ it('should read string variables in key.output', async function() {
const xml = stripIndent`
@@ -165,8 +165,8 @@ describe('visual-keyboard-compiler', function() {
-
+
`;
@@ -177,7 +177,7 @@ describe('visual-keyboard-compiler', function() {
assert.equal(vk.keys[0].text, '2');
});
- it.skip('should read string variables in display.display', async function() {
+ it('should read string variables in display.display', async function() {
const xml = stripIndent`
@@ -192,8 +192,8 @@ describe('visual-keyboard-compiler', function() {
-
+
`;