encode_kn_arb_files.dart 3.24 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7 8 9
// The utility function `encodeKnArbFiles` replaces the material_kn.arb
// and cupertino_kn.arb files in flutter_localizations/packages/lib/src/l10n
// with versions where the contents of the localized strings have been
// replaced by JSON escapes. This is done because some of those strings
// contain characters that can crash Emacs on Linux. There is more information
10 11 12
// here: https://github.com/flutter/flutter/issues/36704 and in the README
// in flutter_localizations/packages/lib/src/l10n.
//
13 14
// This utility is run by `gen_localizations.dart` if --overwrite is passed
// in as an option.
15

16 17
// @dart = 2.8

18 19 20 21 22
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as path;

23
import '../localizations_utils.dart';
24

25
Map<String, dynamic> _loadBundle(File file) {
26 27
  if (!FileSystemEntity.isFileSync(file.path))
    exitWithError('Unable to find input file: ${file.path}');
28
  return json.decode(file.readAsStringSync()) as Map<String, dynamic>;
29 30
}

31
void _encodeBundleTranslations(Map<String, dynamic> bundle) {
32
  for (final String key in bundle.keys) {
33 34 35 36
    // The ARB file resource "attributes" for foo are called @foo. Don't need
    // to encode them.
    if (key.startsWith('@'))
      continue;
37
    final String translation = bundle[key] as String;
38 39 40 41 42 43 44 45 46
    // Rewrite the string as a series of unicode characters in JSON format.
    // Like "\u0012\u0123\u1234".
    bundle[key] = translation.runes.map((int code) {
      final String codeString = '00${code.toRadixString(16)}';
      return '\\u${codeString.substring(codeString.length - 4)}';
    }).join();
  }
}

47
void _checkEncodedTranslations(Map<String, dynamic> encodedBundle, Map<String, dynamic> bundle) {
48 49
  bool errorFound = false;
  const JsonDecoder decoder = JsonDecoder();
50
  for (final String key in bundle.keys) {
51 52 53 54 55 56 57 58 59
    if (decoder.convert('"${encodedBundle[key]}"') != bundle[key]) {
      stderr.writeln('  encodedTranslation for $key does not match original value "${bundle[key]}"');
      errorFound = true;
    }
  }
  if (errorFound)
    exitWithError('JSON unicode translation encoding failed');
}

60
void _rewriteBundle(File file, Map<String, dynamic> bundle) {
61 62
  final StringBuffer contents = StringBuffer();
  contents.writeln('{');
63
  for (final String key in bundle.keys) {
64 65 66 67 68 69
    contents.writeln('  "$key": "${bundle[key]}"${key == bundle.keys.last ? '' : ','}');
  }
  contents.writeln('}');
  file.writeAsStringSync(contents.toString());
}

70 71 72
void encodeKnArbFiles(Directory directory) {
  final File materialArbFile = File(path.join(directory.path, 'material_kn.arb'));
  final File cupertinoArbFile = File(path.join(directory.path, 'cupertino_kn.arb'));
73

74 75
  final Map<String, dynamic> materialBundle = _loadBundle(materialArbFile);
  final Map<String, dynamic> cupertinoBundle = _loadBundle(cupertinoArbFile);
76

77 78
  _encodeBundleTranslations(materialBundle);
  _encodeBundleTranslations(cupertinoBundle);
79

80 81
  _checkEncodedTranslations(materialBundle, _loadBundle(materialArbFile));
  _checkEncodedTranslations(cupertinoBundle, _loadBundle(cupertinoArbFile));
82

83 84
  _rewriteBundle(materialArbFile, materialBundle);
  _rewriteBundle(cupertinoArbFile, cupertinoBundle);
85
}