Repository: iLib-js/ilib-mono-webos
Pull request #17: webos-dart: Fix a bug where the string is not extracted when the variable types are defined in args
Author: login: gouniLee
Labels: name: bug fix
Created: 2025-03-14T05:18:35Z | Merged: 2025-03-25T01:13:08Z

## Description
Fix a bug where the string is not extracted when the variable types are defined in args
for example, `translate('The lowest temp is {arg1} and the highest temp is {arg2}.', args: <String, int>{'arg1': 15, 'arg2': 30})`

Previously, The format that could be extracted when using args was as follows:
`translate("{arg1} app cannot be deleted.", arg:{"arg1": "Settings"})`



Diff:
diff --git a/.changeset/silent-coats-remain.md b/.changeset/silent-coats-remain.md
new file mode 100644
index 000000000..00dc06237
--- /dev/null
+++ b/.changeset/silent-coats-remain.md
@@ -0,0 +1,5 @@
+---
+"ilib-loctool-webos-dart": patch
+---
+
+Fix a bug where the string is not extracted when the variable types are defined in args
diff --git a/.changeset/swift-shirts-give.md b/.changeset/swift-shirts-give.md
new file mode 100644
index 000000000..3d972ddc7
--- /dev/null
+++ b/.changeset/swift-shirts-give.md
@@ -0,0 +1,6 @@
+---
+"ilib-loctool-webos-dist": patch
+---
+
+- ilib-loctool-webos-dart:
+  - Fix a bug where the string is not extracted when the variable types are defined in args
diff --git a/packages/ilib-loctool-webos-dart/DartFile.js b/packages/ilib-loctool-webos-dart/DartFile.js
index f74b5ea82..fa2464c80 100644
--- a/packages/ilib-loctool-webos-dart/DartFile.js
+++ b/packages/ilib-loctool-webos-dart/DartFile.js
@@ -1,7 +1,7 @@
 /*
  * DartFile.js - plugin to extract resources from a Dart source code file
  *
- * Copyright (c) 2023-2024, JEDLSoft
+ * Copyright (c) 2023-2025, JEDLSoft
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -116,11 +116,12 @@ DartFile.prototype.makeKey = function(source) {
 translate("High")
 translate("High", key: "home_connect_210") // will be supported for webos
 translate("{arg1} app cannot be deleted.", arg:{"arg1": "Settings"})
+translate("The lowest temp is {arg1}", args: <String, int>{"arg1": 15})
 translate("The lowest temperature is {arg1} and the highest temperature is {arg2}.", arg:{"arg1": 15, "arg2": 30})
 */
 var reTranslate = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\)/g);
 var reTranslateWithKey = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*(key)\s*\:\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\)/g);
-var reTranslateWithArg = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*args\s*\:\s*\{(.*)\}\s*\)/g);
+var reTranslateWithArg = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*args\s*\:/g);
 var reTranslatePlural = new RegExp(/translatePlural\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*(.*)\)/g);
 var reI18nComment = new RegExp("//\\s*i18n\\s*:\\s*(.*)$");
 
diff --git a/packages/ilib-loctool-webos-dart/test/DartFile.test.js b/packages/ilib-loctool-webos-dart/test/DartFile.test.js
index c442d7d87..6bbeec69d 100644
--- a/packages/ilib-loctool-webos-dart/test/DartFile.test.js
+++ b/packages/ilib-loctool-webos-dart/test/DartFile.test.js
@@ -1,7 +1,7 @@
 /*
  * DartFile.test.js - test the Dart file handler object.
  *
- * Copyright (c) 2023-2024, JEDLSoft
+ * Copyright (c) 2023-2025, JEDLSoft
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -286,6 +286,66 @@ describe("dartfile", function() {
         expect(r.getSource()).toBe(" {arg1} app cannot be deleted. ");
         expect(r.getKey()).toBe(" {arg1} app cannot be deleted. ");
     });
+    test("DartFileParseSimpleWithArgWithTypedefined", function() {
+        expect.assertions(5);
+
+        var d = new DartFile({
+            project: p,
+            pathName: undefined,
+            type: dft
+        });
+        expect(d).toBeTruthy();
+
+        d.parse('translate("The lowest temp is {arg1}", args: <String, String>{"arg1": "15"}),');
+
+        var set = d.getTranslationSet();
+        expect(set).toBeTruthy();
+
+        var r = set.getBySource("The lowest temp is {arg1}");
+        expect(r).toBeTruthy();
+        expect(r.getSource()).toBe("The lowest temp is {arg1}");
+        expect(r.getKey()).toBe("The lowest temp is {arg1}");
+    });
+    test("DartFileParseSimpleWithArgWithTypedefined2", function() {
+        expect.assertions(5);
+
+        var d = new DartFile({
+            project: p,
+            pathName: undefined,
+            type: dft
+        });
+        expect(d).toBeTruthy();
+
+        d.parse('translate("The lowest temp is {arg1} and the highest temp is {arg2}.", args: <String, int>{"arg1": 15, "arg2": 30}),');
+
+        var set = d.getTranslationSet();
+        expect(set).toBeTruthy();
+
+        var r = set.getBySource("The lowest temp is {arg1} and the highest temp is {arg2}.");
+        expect(r).toBeTruthy();
+        expect(r.getSource()).toBe("The lowest temp is {arg1} and the highest temp is {arg2}.");
+        expect(r.getKey()).toBe("The lowest temp is {arg1} and the highest temp is {arg2}.");
+    });
+    test("DartFileParseSimpleWithArgWithTypedefined3", function() {
+        expect.assertions(5);
+
+        var d = new DartFile({
+            project: p,
+            pathName: undefined,
+            type: dft
+        });
+        expect(d).toBeTruthy();
+
+        d.parse("translate('The lowest temp is {arg1} and the highest temp is {arg2}.', args: <String, int>{'arg1': 15, 'arg2': 30}),");
+
+        var set = d.getTranslationSet();
+        expect(set).toBeTruthy();
+
+        var r = set.getBySource("The lowest temp is {arg1} and the highest temp is {arg2}.");
+        expect(r).toBeTruthy();
+        expect(r.getSource()).toBe("The lowest temp is {arg1} and the highest temp is {arg2}.");
+        expect(r.getKey()).toBe("The lowest temp is {arg1} and the highest temp is {arg2}.");
+    });
     test("DartFileParseSimpleIgnoreWhitespace", function() {
         expect.assertions(5);
 
@@ -881,7 +941,7 @@ describe("dartfile", function() {
         expect(set.size()).toBe(0);
     });
     test("DartFileTest2", function() {
-        expect.assertions(8);
+        expect.assertions(11);
 
         var d = new DartFile({
             project: p,
@@ -893,7 +953,7 @@ describe("dartfile", function() {
         d.extract();
 
         var set = d.getTranslationSet();
-        expect(set.size()).toBe(4);
+        expect(set.size()).toBe(5);
 
         var r = set.getBySource("Track");
         expect(r).toBeTruthy();
@@ -906,9 +966,14 @@ describe("dartfile", function() {
         expect(r).toBeTruthy();
         expect(r[0].getSource()).toBe("1#At least 1 letter|#At least {num} letters");
         expect(r[0].getKey()).toBe("1#At least 1 letter|#At least {num} letters");
+
+        var r = set.getBySource("first number {arg1}, second number {arg2}, and third number {arg3}");
+        expect(r).toBeTruthy();
+        expect(r.getSource()).toBe("first number {arg1}, second number {arg2}, and third number {arg3}");
+        expect(r.getKey()).toBe("first number {arg1}, second number {arg2}, and third number {arg3}");
     });
     test("DartFileTest3", function() {
-        expect.assertions(17);
+        expect.assertions(20);
 
         var d = new DartFile({
             project: p,
@@ -920,7 +985,7 @@ describe("dartfile", function() {
         d.extract();
 
         var set = d.getTranslationSet();
-        expect(set.size()).toBe(5);
+        expect(set.size()).toBe(6);
 
         var r = set.getBySource("WOWCAST ({arg1})");
         expect(r).toBeTruthy();
@@ -946,6 +1011,11 @@ describe("dartfile", function() {
         expect(r).toBeTruthy();
         expect(r.getSource()).toBe("The lowest temp is {arg1} and the highest temp is {arg2}.");
         expect(r.getKey()).toBe("The lowest temp is {arg1} and the highest temp is {arg2}.");
+
+        var r = set.getBySource("Exclusive features for {%model} are all gathered here.");
+        expect(r).toBeTruthy();
+        expect(r.getSource()).toBe("Exclusive features for {%model} are all gathered here.");
+        expect(r.getKey()).toBe("Exclusive features for {%model} are all gathered here.");
     });
     test("DartPseudoLocalization1", function() {
         expect.assertions(4);
diff --git a/packages/ilib-loctool-webos-dart/test/testfiles/t2.dart b/packages/ilib-loctool-webos-dart/test/testfiles/t2.dart
index 0392f6f0f..274585a45 100644
--- a/packages/ilib-loctool-webos-dart/test/testfiles/t2.dart
+++ b/packages/ilib-loctool-webos-dart/test/testfiles/t2.dart
@@ -2,4 +2,5 @@ translate("Save Bookmark");
 translate("Track", key: "music_track");
 translate("List", args: {"arg1": "music_track"});
 
-translatePlural('1#At least 1 letter|#At least {num} letters', num);
\ No newline at end of file
+translatePlural('1#At least 1 letter|#At least {num} letters', num);
+translate('first number {arg1}, second number {arg2}, and third number {arg3}', args: <String, int>{'arg1': 15, 'arg2': 30, 'arg3': 47});
diff --git a/packages/ilib-loctool-webos-dart/test/testfiles/t3.dart b/packages/ilib-loctool-webos-dart/test/testfiles/t3.dart
index 90bf2674b..3921cefff 100644
--- a/packages/ilib-loctool-webos-dart/test/testfiles/t3.dart
+++ b/packages/ilib-loctool-webos-dart/test/testfiles/t3.dart
@@ -22,3 +22,8 @@ Text(
         'The lowest temp is {arg1} and the highest temp is {arg2}.',
         args: {'arg1': 15, 'arg2': 30}                 ),
     style: Style.textStyle),
+
+static String sn_home_0016(tvModel) => translate(
+        'Exclusive features for {%model} are all gathered here.',
+        args: {'%model': tvModel},    // not extracted
+      );
\ No newline at end of file
diff --git a/packages/samples-loctool/webos-dart/src/msg.dart b/packages/samples-loctool/webos-dart/src/msg.dart
index 158b8fcef..afa4d8f88 100644
--- a/packages/samples-loctool/webos-dart/src/msg.dart
+++ b/packages/samples-loctool/webos-dart/src/msg.dart
@@ -13,4 +13,12 @@ translate("OK");
 translate(
   '{appName} app cannot be deleted.',
     args: {'appName': 'Settings'}
-    ),
\ No newline at end of file
+    ),
+
+translate('The first option is {arg1}.', args: <String, String>{'arg1': 'music'});
+
+
+static String sn_home_0016(tvModel) => translate(
+        'Exclusive features for {%TV_model} are all gathered here.',
+        args: {'%TV_model': tvModel},
+      );
\ No newline at end of file
diff --git a/packages/samples-loctool/webos-dart/test/testResources.js b/packages/samples-loctool/webos-dart/test/testResources.js
index f4a3d1309..b55d4d71b 100644
--- a/packages/samples-loctool/webos-dart/test/testResources.js
+++ b/packages/samples-loctool/webos-dart/test/testResources.js
@@ -67,6 +67,8 @@ function testkoKR(){
     var result4 = loadData["Delete All"];
     var result5 = loadData["Search_all"];
     var result6 = loadData["{appName} app cannot be deleted."];
+    var result7 = loadData["The first option is {arg1}."];
+    var result8 = loadData["Exclusive features for {%TV_model} are all gathered here."];
                   
     logResults(arguments.callee.name, "앱 목록", result1);
     logResults(arguments.callee.name, "앱 등급", result2);
@@ -74,6 +76,8 @@ function testkoKR(){
     logResults(arguments.callee.name, "모두 삭제", result4);
     logResults(arguments.callee.name, "통합 검색", result5);
     logResults(arguments.callee.name, "{appName}앱은 삭제될 수 없습니다.", result6);
+    logResults(arguments.callee.name, "첫 번째 옵션은 {arg1} 입니다.", result7);
+    logResults(arguments.callee.name, "{%TV_model}에서만 제공하는 유용한 기능들이 모여 있어요.", result8);
 
     // appinfo
     var result7 = loadDataAppinfoData["title"];
diff --git a/packages/samples-loctool/webos-dart/xliffs/ko-KR.xliff b/packages/samples-loctool/webos-dart/xliffs/ko-KR.xliff
index 0de6386a9..f8f6dccb7 100644
--- a/packages/samples-loctool/webos-dart/xliffs/ko-KR.xliff
+++ b/packages/samples-loctool/webos-dart/xliffs/ko-KR.xliff
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <xliff version="2.0" srcLang="en-KR" trgLang="ko-KR" xmlns:l="http://ilib-js.com/loctool">
   <file id="sample-webos-dart_f1" original="sample-webos-dart">
-    <group id="sample-webos-json_g1" name="javascript">
+    <group id="sample-webos-json_g1" name="x-dart">
       <unit id="1">
         <segment>
           <source>Live TV</source>
@@ -46,6 +46,21 @@
         <target>{appName}앱은 삭제될 수 없습니다.</target>
         </segment>
       </unit>
+      <unit id="6">
+        <segment>
+        <source>The first option is {arg1}.</source>
+        <target>첫 번째 옵션은 {arg1} 입니다.</target>
+        </segment>
+      </unit>
+      <unit id="676">
+        <notes>
+          <note>notes</note>
+        </notes>
+        <segment>
+          <source>Exclusive features for {%TV_model} are all gathered here.</source>
+          <target>{%TV_model}에서만 제공하는 유용한 기능들이 모여 있어요.</target>
+        </segment>
+      </unit>
     </group>
   </file>
 </xliff>
\ No newline at end of file


Reviews:
user: login: ehoogerbeets
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T00:35:02Z
user: login: gouniLee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T08:20:30Z
user: login: ehoogerbeets
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T21:51:10Z

Review comments:
diff_hunk: @@ -116,11 +116,12 @@ DartFile.prototype.makeKey = function(source) {
 translate("High")
 translate("High", key: "home_connect_210") // will be supported for webos
 translate("{arg1} app cannot be deleted.", arg:{"arg1": "Settings"})
+translate("The lowest temp is {arg1}", args: <String, int>{"arg1": 15})
 translate("The lowest temperature is {arg1} and the highest temperature is {arg2}.", arg:{"arg1": 15, "arg2": 30})
 */
 var reTranslate = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\)/g);
 var reTranslateWithKey = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*(key)\s*\:\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\)/g);
-var reTranslateWithArg = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*args\s*\:\s*\{(.*)\}\s*\)/g);
+var reTranslateWithArg = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*args\s*\:\s*(\<.*\>)?\s*\{(.*)\}\s*\)/g);
path: packages/ilib-loctool-webos-dart/DartFile.js
user: login: ehoogerbeets
body: ```suggestion
var reTranslateWithArg = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*args\s*\:/g);
```
created_at: 2025-03-19T00:32:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -116,11 +116,12 @@ DartFile.prototype.makeKey = function(source) {
 translate("High")
 translate("High", key: "home_connect_210") // will be supported for webos
 translate("{arg1} app cannot be deleted.", arg:{"arg1": "Settings"})
+translate("The lowest temp is {arg1}", args: <String, int>{"arg1": 15})
 translate("The lowest temperature is {arg1} and the highest temperature is {arg2}.", arg:{"arg1": 15, "arg2": 30})
 */
 var reTranslate = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\)/g);
 var reTranslateWithKey = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*(key)\s*\:\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\)/g);
-var reTranslateWithArg = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*args\s*\:\s*\{(.*)\}\s*\)/g);
+var reTranslateWithArg = new RegExp(/translate\s*\(\s*("((\\"|[^"])*)"|'((\\'|[^'])*)')\s*\,\s*args\s*\:\s*(\<.*\>)?\s*\{(.*)\}\s*\)/g);
path: packages/ilib-loctool-webos-dart/DartFile.js
user: login: gouniLee
body: I updated it. I didn't change the reTranslationWithKey expression in sameway. because it needs to extract the key value, which is different from args.
created_at: 2025-03-19T08:20:30Z
author_association: CONTRIBUTOR

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-03-14T05:18:39Z
body: ###  🦋  Changeset detected

Latest commit: c48e5197c46053b9d4a4963dda9dc121190be17f

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 3 packages</summary>

  | Name                    | Type  |
| ----------------------- | ----- |
| ilib-loctool-webos-dart | Patch |
| ilib-loctool-webos-dist | Patch |
| sample-webos-dart       | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/iLib-js/ilib-mono-webos/new/dart-stringextract?filename=.changeset/tasty-gorillas-invite.md&value=---%0A%22ilib-loctool-webos-dart%22%3A%20patch%0A%22sample-webos-dart%22%3A%20patch%0A---%0A%0Awebos-dart%3A%20Fix%20a%20bug%20where%20the%20string%20is%20not%20extracted%20when%20the%20variable%20types%20are%20defined%20in%20args%0A)


author_association: NONE
user: login: codecov[bot]
created_at: 2025-03-14T05:20:42Z
body: ## [Codecov](https://app.codecov.io/gh/iLib-js/ilib-mono-webos/pull/17?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iLib-js) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 49.64%. Comparing base [(`9180ac0`)](https://app.codecov.io/gh/iLib-js/ilib-mono-webos/commit/9180ac00b87a61dc78e3f69fe0884318dd1f8233?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iLib-js) to head [(`c48e519`)](https://app.codecov.io/gh/iLib-js/ilib-mono-webos/commit/c48e5197c46053b9d4a4963dda9dc121190be17f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iLib-js).
> Report is 164 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main      #17   +/-   ##
=======================================
  Coverage   49.64%   49.64%           
=======================================
  Files          18       18           
  Lines        2689     2689           
  Branches      651      651           
=======================================
  Hits         1335     1335           
  Misses       1091     1091           
  Partials      263      263           
```

| [Files with missing lines](https://app.codecov.io/gh/iLib-js/ilib-mono-webos/pull/17?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iLib-js) | Coverage Δ | |
|---|---|---|
| [packages/ilib-loctool-webos-dart/DartFile.js](https://app.codecov.io/gh/iLib-js/ilib-mono-webos/pull/17?src=pr&el=tree&filepath=packages%2Filib-loctool-webos-dart%2FDartFile.js&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iLib-js#diff-cGFja2FnZXMvaWxpYi1sb2N0b29sLXdlYm9zLWRhcnQvRGFydEZpbGUuanM=) | `89.34% <100.00%> (ø)` | |

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE