Skip to content

Commit

Permalink
[ISSUE-25] Fixes bug with placeholder wrong formatting resulting to i…
Browse files Browse the repository at this point in the history
…nconsistencies with placeholder objects and translation-keys (#29)

## Description

Fixes bug with placeholder wrong formatting resulting to inconsistencies
with placeholder objects as mentioned
[here](#25)

## Please check the following boxes

<!--- Put an `X` in all the boxes that apply: -->

- [x] Pull Request title is consistent with the implemented feature, fix
etc.
- [x] I have followed proper descriptive code style and conventions
- [x] The code is self-documenting and has no unnecessary comments. I
named the functions and variables to clearly describe their purpose.
- [ ] I have added Unit Tests and coverage is 70%+
- [x] I have tested and verified this implementation and it works as
expected
  • Loading branch information
kwado-tech authored Sep 20, 2024
1 parent 42c79b6 commit 73aad74
Show file tree
Hide file tree
Showing 12 changed files with 1,129 additions and 1,131 deletions.
2 changes: 1 addition & 1 deletion example/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
8 changes: 4 additions & 4 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down Expand Up @@ -275,7 +275,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down Expand Up @@ -352,7 +352,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -401,7 +401,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
494 changes: 247 additions & 247 deletions example/lib/localization/gen-l10n/app_localizations.dart

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

462 changes: 231 additions & 231 deletions example/lib/localization/gen-l10n/app_localizations_ar.dart

Large diffs are not rendered by default.

662 changes: 331 additions & 331 deletions example/lib/localization/gen-l10n/app_localizations_de.dart

Large diffs are not rendered by default.

494 changes: 247 additions & 247 deletions example/lib/localization/gen-l10n/app_localizations_en.dart

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/lib/localization/translations/local/app_ar.arb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/lib/localization/translations/local/app_de.arb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/lib/localization/translations/local/app_en.arb

Large diffs are not rendered by default.

128 changes: 63 additions & 65 deletions l10n_mapper_generator/scripts/format_localization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,9 @@ class FormatLocalization {
return camelCaseRegExp.hasMatch(input);
}

bool startsWithUppercase(String input) {
final substring = input.substring(0, 1);

if (substring == '@') {
return input.substring(0, 2).toLowerCase() == input.substring(0, 2);
}

return substring.toUpperCase() == substring;
}

String toLocalizationKeyCase(String input) {
final substring = input.substring(0, 1);

if (substring == '@') {
return input.substring(0, 2).toLowerCase() + input.substring(2);
}

return substring.toLowerCase() + input.substring(1);
}

bool isDirectSubKeyOfPlaceholders(Map<String, dynamic> json, String keyToCheck) {
for (var key in json.keys) {
if (json[key] is Map && json[key].containsKey('placeholders')) {
final placeholders = json[key]['placeholders'];

if (placeholders is Map) {
return placeholders.containsKey(keyToCheck);
}
}
}
return false;
}
bool isLowerCase(String input) => input == input.toLowerCase();

/// Modifies key to replace matching predicates and convert match to camel-case if predicate-value is empty (if its not a placeholder object)
String toCamelCase(String input, List<String> separators) {
if (separators.isEmpty || isCamelCase(input)) return input;

Expand All @@ -70,23 +40,60 @@ class FormatLocalization {
return camelCaseString;
}

String convertPlaceholdersToCamelCase(String input, List<String> separators) {
if (separators.isEmpty || isCamelCase(input)) return input;
String handleDefaultCase(String input) {
if (input.isEmpty) return input;

final firstChar = input[0];

if (firstChar == '@' && input.length > 1 && input[1] == input[1].toUpperCase()) {
return input.toLowerCase();
}

if (firstChar == firstChar.toUpperCase()) return input.toLowerCase();

return input;
}

String formatKeys({
required String input,
required Map<String, dynamic> predicates,
required List<String> emptyPredicateKeys,
}) {
String key = input.replaceAll('"', '').trim();

key = toCamelCase(key, emptyPredicateKeys)
.split(StringConstants.emptyString)
.map((e) => predicates[e] ?? e)
.join()
.trim();

final substring = key.substring(0, 1);

return substring == '@' ? '@${handleDefaultCase(key.substring(1))}' : handleDefaultCase(key);
}

String formatValuePlaceHolders({
required List<String> input,
required Map<String, dynamic> predicates,
required List<String> emptyPredicateKeys,
}) {
String value = input.join().trimLeft();

final placeholderPattern = RegExp(r'\{\s*(.*?)\s*\}');

// use String.replaceAllMapped to process each placeholder
return input.replaceAllMapped(placeholderPattern, (match) {
return value.replaceAllMapped(placeholderPattern, (match) {
// extract the placeholder content without the curly braces
String placeholderContent = match.group(1) ?? '';
String content = match.group(1) ?? '';

// if (isCamelCase(placeholderContent)) return '{$placeholderContent}';

// convert the placeholder content to camel case
String camelCasePlaceholder = toCamelCase(placeholderContent, separators);
final placeholder = toCamelCase(content, emptyPredicateKeys)
.split(StringConstants.emptyString)
.map((e) => predicates[e] ?? e)
.join()
.trim();

// rebuild the placeholder with curly braces
return '{$camelCasePlaceholder}';
return '{${handleDefaultCase(placeholder)}}';
});
}

Expand Down Expand Up @@ -148,34 +155,25 @@ class FormatLocalization {
await inputFile.openRead().transform(utf8.decoder).transform(const LineSplitter()).forEach((line) {
final parts = line.split(':');

String modifiedTranslationKey = parts[0].replaceAll('"', '').trim();
String modifiedTranslationValue = parts.sublist(1).join().trimLeft();

// format translation-value
// modify key to replace matching predicates and convert match to camel-case if predicate-value is empty (if its not a placeholder object)
modifiedTranslationKey = toCamelCase(modifiedTranslationKey, emptyPredicateKeys);

modifiedTranslationKey =
modifiedTranslationKey.split(StringConstants.emptyString).map((e) => predicates[e] ?? e).join().trim();

// convert the key to camel-case if it's not in a placeholders block and not camel-case
if (startsWithUppercase(modifiedTranslationKey)) {
modifiedTranslationKey = toLocalizationKeyCase(modifiedTranslationKey);
}

// format translation-value
modifiedTranslationValue = convertPlaceholdersToCamelCase(modifiedTranslationValue, emptyPredicateKeys);
final translationKey = formatKeys(
input: parts[0],
predicates: predicates,
emptyPredicateKeys: emptyPredicateKeys,
);

modifiedTranslationValue =
modifiedTranslationValue.split(StringConstants.emptyString).map((e) => predicates[e] ?? e).join().trim();
final translationValue = formatValuePlaceHolders(
input: parts.sublist(1),
predicates: predicates,
emptyPredicateKeys: emptyPredicateKeys,
);

if ('"$modifiedTranslationKey"' == '"@@locale"') {
lines.add('"$modifiedTranslationKey": "${option.locale.getValue()}",');
if ('"$translationKey"' == '"@@locale"') {
lines.add('"$translationKey": "${option.locale.getValue()}",');
} else {
if (modifiedTranslationValue.isEmpty) {
lines.add(modifiedTranslationKey);
if (translationValue.isEmpty) {
lines.add(translationKey);
} else {
lines.add('"$modifiedTranslationKey": $modifiedTranslationValue');
lines.add('"$translationKey": $translationValue');
}
}
});
Expand Down

0 comments on commit 73aad74

Please sign in to comment.