From 6f6a66e8cc71e3acd32d554f457cebd3e46312eb Mon Sep 17 00:00:00 2001 From: Levente Asztalos Date: Thu, 27 Nov 2025 09:53:16 +0100 Subject: [PATCH 1/3] feat: add undeclared placeholders to the placeholders list --- lib/src/common/gen_l10n_types.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/common/gen_l10n_types.dart b/lib/src/common/gen_l10n_types.dart index 1878cd3..cbddfe7 100644 --- a/lib/src/common/gen_l10n_types.dart +++ b/lib/src/common/gen_l10n_types.dart @@ -542,6 +542,7 @@ class Message { traversalStack.addAll(node.children); } } + placeholders.addAll(undeclaredPlaceholders); } } From 5d5d67bba69cfa0590701f3b3050ad35e1e4a1b7 Mon Sep 17 00:00:00 2001 From: Yurii Date: Thu, 27 Nov 2025 23:41:56 +0200 Subject: [PATCH 2/3] feat: add undeclared placeholders to the placeholders list tests --- test/crowdin_extractor_test.dart | 73 ++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/test/crowdin_extractor_test.dart b/test/crowdin_extractor_test.dart index cc599fd..13a93f8 100644 --- a/test/crowdin_extractor_test.dart +++ b/test/crowdin_extractor_test.dart @@ -139,4 +139,77 @@ void main() { expect(result, 'No selection chosen'); }); }); + + group('Placeholders without metadata', () { + Extractor extractor = Extractor(); + + test('should infer and substitute simple placeholders without @metadata', () { + var otaArb = { + "@@locale": "en", + "pageInfo": "Page {current} of {total}", + }; + + final result = extractor.getText( + 'en', + AppResourceBundle(otaArb), + 'pageInfo', + {'current': 3, 'total': 10}, + ); + + expect(result, 'Page 3 of 10'); + }); + + test('should handle multiple placeholders without metadata', () { + var otaArb = { + "@@locale": "en", + "greeting": "Hello {userName}, you have {count} messages", + }; + + final result = extractor.getText( + 'en', + AppResourceBundle(otaArb), + 'greeting', + {'userName': 'John', 'count': 10}, + ); + + expect(result, 'Hello John, you have 10 messages'); + }); + + test('should handle mixed: some placeholders with metadata, some without', () { + var mixedArb = { + "@@locale": "en", + "greeting": "Hello {userName}, you are {age} years old", + "@greeting": { + "placeholders": { + "userName": {"type": "String"} + } + } + }; + + final result = extractor.getText( + 'en', + AppResourceBundle(mixedArb), + 'greeting', + {'userName': 'Alice', 'age': 25}, + ); + + expect(result, 'Hello Alice, you are 25 years old'); + }); + + test('should infer placeholders from select expressions without metadata', () { + var selectArb = { + "@@locale": "en", + "gender": "{choice, select, male{He} female{She} other{They}}", + }; + + final bundle = AppResourceBundle(selectArb); + final message = Message(bundle, 'gender', false); + + expect(message.placeholders.containsKey('choice'), true); + expect(message.placeholders['choice']?.isSelect, true); + + final resultMale = extractor.getText('en', bundle, 'gender', {'choice': 'male'}); + expect(resultMale, 'He'); + }); + }); } From 098dc3245a5edfaabacb25eff15133a8d21f7759 Mon Sep 17 00:00:00 2001 From: Yurii Date: Thu, 27 Nov 2025 23:56:27 +0200 Subject: [PATCH 3/3] format --- test/crowdin_extractor_test.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/crowdin_extractor_test.dart b/test/crowdin_extractor_test.dart index 13a93f8..7c838b7 100644 --- a/test/crowdin_extractor_test.dart +++ b/test/crowdin_extractor_test.dart @@ -143,7 +143,8 @@ void main() { group('Placeholders without metadata', () { Extractor extractor = Extractor(); - test('should infer and substitute simple placeholders without @metadata', () { + test('should infer and substitute simple placeholders without @metadata', + () { var otaArb = { "@@locale": "en", "pageInfo": "Page {current} of {total}", @@ -175,7 +176,8 @@ void main() { expect(result, 'Hello John, you have 10 messages'); }); - test('should handle mixed: some placeholders with metadata, some without', () { + test('should handle mixed: some placeholders with metadata, some without', + () { var mixedArb = { "@@locale": "en", "greeting": "Hello {userName}, you are {age} years old", @@ -196,7 +198,8 @@ void main() { expect(result, 'Hello Alice, you are 25 years old'); }); - test('should infer placeholders from select expressions without metadata', () { + test('should infer placeholders from select expressions without metadata', + () { var selectArb = { "@@locale": "en", "gender": "{choice, select, male{He} female{She} other{They}}", @@ -208,7 +211,8 @@ void main() { expect(message.placeholders.containsKey('choice'), true); expect(message.placeholders['choice']?.isSelect, true); - final resultMale = extractor.getText('en', bundle, 'gender', {'choice': 'male'}); + final resultMale = + extractor.getText('en', bundle, 'gender', {'choice': 'male'}); expect(resultMale, 'He'); }); });