This repository has been archived by the owner on Aug 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
2 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/// This library provides storage for localized messages in a lookup table. | ||
/// This is used for optimizing localized string lookups for web | ||
/// development when using ACX sharded localization (go/acx-localization). | ||
/// This library relies on javascript features. | ||
/// Dart2js generates calls to this library when using sharded localization; | ||
/// clients shouldn't make the call to this library directly. | ||
library intl_message_table; | ||
|
||
import 'dart:convert'; | ||
import 'dart:js_util' as js_util; | ||
|
||
/// Internal representation of a translated string; either a single string (for | ||
/// non-constructed strings) or an array of strings and argument indexes. | ||
/// For example, the constructed string 'My name is ${name}, how are you?' | ||
/// is represented as ['My name is ', 0, ', how are you?']. | ||
/// This representation matches the code generated by the 'generate_from_xtb' | ||
/// tool. | ||
class _Message { | ||
// Each element is either a string or an integer representing the argument index. | ||
final List<dynamic> values; | ||
|
||
_Message(this.values); | ||
|
||
_Message.fromString(String string) : this([string]); | ||
|
||
// Most messages consist of only a single string; only constructed strings | ||
// have more than one element. This function is for non-constructed strings. | ||
String getString() { | ||
return values.first.toString(); | ||
} | ||
|
||
List<dynamic> getList() { | ||
return values; | ||
} | ||
} | ||
|
||
/// Functions for loading translations for messages based on an index. | ||
/// Each compilation unit registers the translations it needs in a field on the | ||
/// Dom under a unique id for its app as a json string. Messages are referenced | ||
/// by index in the code. When a message is referenced, the translations for | ||
/// that app are parsed and inserted into the table. | ||
class AcxIntlMessageTable { | ||
// Indexed list of messages. If a message isn't yet loaded, the entry will be | ||
// null. | ||
static List<_Message?> _internalArray = []; | ||
|
||
static String lookup(int id) { | ||
return _lookupMessagebyId(id).getString(); | ||
} | ||
|
||
static List<dynamic> lookupList(int id) => _lookupMessagebyId(id).getList(); | ||
|
||
static _Message? _getMessage(int id) => | ||
id < _internalArray.length ? _internalArray[id] : null; | ||
|
||
static _Message _lookupMessagebyId(int id) { | ||
var message = _getMessage(id); | ||
if (message != null) { | ||
return message; | ||
} | ||
// Copy outstanding messages locally | ||
// TODO(b/274616739): Use appId provided by environment. | ||
// Maybe something like: | ||
// const String.fromEnvironment('dart.dart2js.appid'); | ||
final appId = 'MyAppId'; | ||
|
||
for (var message in _popPendingTranslations(appId)) { | ||
loadMessages(message); | ||
} | ||
message = _getMessage(id); | ||
if (message == null) { | ||
throw ArgumentError('Unable to locate string $id'); | ||
} | ||
return message; | ||
} | ||
|
||
/// Translations for a language are lazily parsed into the map when requested on | ||
/// a per-app basis. | ||
static List<String> _popPendingTranslations(String appId) { | ||
final result = js_util.getProperty<List<String>>( | ||
js_util.getProperty(js_util.globalThis, r'$_intl_pending_translations'), | ||
appId); | ||
js_util.setProperty<List<String>>( | ||
js_util.getProperty(js_util.globalThis, r'$_intl_pending_translations'), | ||
appId, []); | ||
return result; | ||
} | ||
|
||
static void loadMessages(String json_messages) { | ||
var parsed = json.decode(json_messages); | ||
parsed.forEach((index_string, message) { | ||
int index = int.parse(index_string); | ||
// Grow array to fit in new message. | ||
if (index >= _internalArray.length) _internalArray.length = index + 1; | ||
_internalArray[index] = _Message(message); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import 'package:intl/acx_sharded_intl.dart'; | ||
import 'package:test/test.dart'; | ||
import 'dart:js_util' as js_util; | ||
import 'dart:convert'; | ||
|
||
void main() { | ||
setUp(() { | ||
final testStrings1 = { | ||
'0': ['Test String 0'], | ||
'1': ['Test String 1'], | ||
'2': ['Test String 2'] | ||
}; | ||
final testStrings2 = { | ||
'3': ['Test String 3'], | ||
'4': ['Test String 4'], | ||
'5': ['Test String 5'], | ||
'6': ['Constructed ', 0, ' String 6'] | ||
}; | ||
final encoding1 = jsonEncode(testStrings1); | ||
final encoding2 = jsonEncode(testStrings2); | ||
js_util.setProperty<Object>(js_util.globalThis, | ||
r'$_intl_pending_translations', js_util.newObject()); | ||
js_util.setProperty( | ||
js_util.getProperty(js_util.globalThis, r'$_intl_pending_translations'), | ||
'MyAppId', | ||
[encoding1, encoding2]); | ||
}); | ||
test('testIntlMessageTableLookup', () { | ||
expect(AcxIntlMessageTable.lookup(1), equals('Test String 1')); | ||
expect(AcxIntlMessageTable.lookup(5), equals('Test String 5')); | ||
expect(AcxIntlMessageTable.lookup(5), equals('Test String 5')); | ||
expect(AcxIntlMessageTable.lookupList(6), | ||
equals(['Constructed ', 0, ' String 6'])); | ||
}); | ||
} |