Skip to content

Commit f8f94e0

Browse files
committed
cleanup
1 parent 01c5055 commit f8f94e0

8 files changed

+279
-281
lines changed

lib/src/arb/arb.dart

+31-34
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
* BSD-style license that can be found in the LICENSE file.
55
*/
66

7-
import 'package:gsheet_to_arb/src/arb/arb_utils.dart';
8-
97
class ArbDocument {
108
String locale;
119
DateTime lastModified;
@@ -16,13 +14,13 @@ class ArbDocument {
1614
Map<String, Object> toJson() {
1715
final _json = <String, Object>{};
1816

19-
_json['_locale'] = locale;
17+
_json['@@locale'] = locale;
2018
_json['@@last_modified'] = lastModified.toIso8601String();
2119

2220
entries.forEach((ArbResource resource) {
23-
_json[resource.id.text] = resource.value.text;
24-
if (resource.hasAttributes) {
25-
_json['@@${resource.id.text}'] = resource.attributes;
21+
_json[resource.key] = resource.value;
22+
if (resource.attributes.isNotEmpty) {
23+
_json['@${resource.key}'] = resource.attributes;
2624
}
2725
});
2826

@@ -51,44 +49,43 @@ class ArbDocument {
5149
}
5250

5351
class ArbResource {
54-
final ArbResourceId id;
55-
final ArbResourceValue value;
52+
final String key;
53+
final String value;
5654
final Map<String, Object> attributes = {};
55+
final List<ArbResourcePlaceholder> placeholders;
56+
final String description;
57+
final String context;
58+
59+
ArbResource(String key, String value,
60+
{this.description = '', this.context = '', this.placeholders = const []})
61+
: key = key,
62+
value = value {
63+
attributes['type'] = 'Text'; // Possible values are "text", "image", "css"
64+
if (placeholders != null) {
65+
attributes['placeholders'] = _formatPlaceholders(placeholders);
66+
}
5767

58-
final bool hasAttributes;
68+
if (description != null && description.isNotEmpty) {
69+
attributes['description'] = description;
70+
}
5971

60-
ArbResource(String id, String value, [this.hasAttributes = true])
61-
: id = ArbResourceId(id),
62-
value = ArbResourceValue(value) {
63-
if (hasAttributes) {
64-
attributes['type'] = 'Text';
65-
attributes['placeholders'] = <String, Object>{};
72+
if (context != null && context.isNotEmpty) {
73+
attributes['context'] = context;
6674
}
6775
}
68-
}
69-
70-
class ArbResourceId {
71-
final String text;
7276

73-
ArbResourceId(this.text);
74-
}
75-
76-
class ArbResourceValue {
77-
final String text;
78-
final placeholders = <ArbResourcePlaceholder>[];
79-
80-
bool get hasPlaceholders => placeholders.isNotEmpty;
81-
82-
ArbResourceValue(this.text) {
83-
var placeholders = findPlaceholders(text);
84-
if (placeholders.isNotEmpty) {
85-
this.placeholders.addAll(placeholders);
86-
}
77+
Map<String, Object> _formatPlaceholders(
78+
List<ArbResourcePlaceholder> placeholders) {
79+
final map = <String, Object>{};
80+
placeholders.forEach((placeholder) => {map[placeholder.name] = {}});
81+
return map;
8782
}
8883
}
8984

9085
class ArbResourcePlaceholder {
9186
final String name;
87+
final String description;
88+
final String example;
9289

93-
ArbResourcePlaceholder(this.name);
90+
ArbResourcePlaceholder({this.name, this.description, this.example});
9491
}

lib/src/arb/arb_utils.dart

-34
This file was deleted.

lib/src/dart/arb_to_dart_generator.dart

+8-9
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,18 @@ class ArbToDartGenerator {
3939
}
4040

4141
Method _getResourceMethod(ArbResource resource) {
42-
if (resource.value.hasPlaceholders) {
42+
if (resource.placeholders.isEmpty) {
4343
var method = Method((MethodBuilder builder) {
4444
var description = resource.attributes['description'];
45-
description ??= resource.id.text;
45+
description ??= resource.key;
4646

47-
var key = resource.id.text;
48-
var value = resource.value.text;
47+
var key = resource.key;
48+
var value = resource.value;
4949

5050
builder.name = _getMethodName(key);
5151

5252
var args = <String>[];
53-
resource.value.placeholders
54-
.forEach((ArbResourcePlaceholder placeholder) {
53+
resource.placeholders.forEach((ArbResourcePlaceholder placeholder) {
5554
builder.requiredParameters.add(Parameter((ParameterBuilder builder) {
5655
args.add(placeholder.name);
5756
builder.name = placeholder.name;
@@ -74,10 +73,10 @@ class ArbToDartGenerator {
7473
Method _getResourceGetter(ArbResource resource) {
7574
final method = Method((MethodBuilder builder) {
7675
var description = resource.attributes['description'];
77-
description ??= resource.id.text;
76+
description ??= resource.key;
7877

79-
var key = resource.id.text;
80-
var value = resource.value.text;
78+
var key = resource.key;
79+
var value = resource.value;
8180

8281
builder
8382
..name = _getMethodName(key)

lib/src/gsheet/ghseet_importer.dart

+53-10
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,68 @@ class GSheetImporter {
5454
}
5555

5656
Future<TranslationsDocument> _importFrom(Spreadsheet spreadsheet) async {
57-
Log.i('Opening ${spreadsheet.spreadsheetUrl}');
57+
Log.i('Importing from: ${spreadsheet.spreadsheetUrl}');
5858

59-
var sheet = spreadsheet.sheets[0];
60-
var rows = sheet.data[0].rowData;
61-
var header = rows[0];
62-
var headerValues = header.values;
59+
final sheet = spreadsheet.sheets[0];
60+
final rows = sheet.data[0].rowData;
61+
final header = rows[0];
62+
final headerValues = header.values;
6363

64-
final languages = List<String>();
64+
final languages = <String>[];
65+
final items = <TranslationRow>[];
6566

66-
for (var column = _SheetRows.first_translation_row;
67+
var firstLanguageColumn = _SheetColumns.first_language_key;
68+
var firstTranslationsRow = _SheetRows.first_translation_row;
69+
70+
var currentCategory = '';
71+
72+
for (var column = firstLanguageColumn;
6773
column < headerValues.length;
6874
column++) {
6975
final language = headerValues[column].formattedValue;
7076
languages.add(language);
7177
}
7278

73-
return TranslationsDocument(
79+
// rows
80+
for (var i = firstTranslationsRow; i < rows.length; i++) {
81+
var row = rows[i];
82+
var languages = row.values;
83+
var key = languages[_SheetColumns.key].formattedValue;
84+
85+
//Skip if empty row is found
86+
if (key == null) {
87+
continue;
88+
}
89+
90+
if (key.startsWith(categoryPrefix)) {
91+
currentCategory = key.substring(categoryPrefix.length);
92+
continue;
93+
}
94+
95+
final description =
96+
languages[_SheetColumns.description].formattedValue ?? '';
97+
98+
final values = row.values
99+
.sublist(firstLanguageColumn, row.values.length)
100+
.map((data) => data.formattedValue)
101+
.toList();
102+
103+
final item = TranslationRow(
104+
key: key,
105+
category: currentCategory,
106+
description: description,
107+
values: values);
108+
109+
items.add(item);
110+
}
111+
112+
final document = TranslationsDocument(
113+
lastModified: DateTime.now(),
74114
languages: languages, //
75-
items: null // TODO
76-
);
115+
items: items);
116+
117+
Log.i('Imported document: ${document.describe()}');
118+
119+
return document;
77120
}
78121
}

lib/src/parser/plurals_parser.dart

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import 'package:gsheet_to_arb/src/arb/arb.dart';
2+
3+
///
4+
/// Plurals
5+
///
6+
enum PluralCase { zero, one, two, few, many, other }
7+
8+
abstract class PluralsStatus {}
9+
10+
class Skip extends PluralsStatus {}
11+
12+
class Consumed extends PluralsStatus {}
13+
14+
class Completed extends PluralsStatus {
15+
final String key;
16+
final ArbResource attributes;
17+
final Map<PluralCase, String> values;
18+
final bool consumed;
19+
20+
Completed({this.key, this.attributes, this.values, this.consumed = false});
21+
}
22+
23+
class PluralsParser {
24+
final _pluralSeparator = '=';
25+
26+
final _pluralKeywords = {
27+
'zero': PluralCase.zero,
28+
'one': PluralCase.one,
29+
'two': PluralCase.two,
30+
'few': PluralCase.few,
31+
'many': PluralCase.many,
32+
'other': PluralCase.other
33+
};
34+
35+
String _key;
36+
ArbResource _attributes;
37+
final _values = <PluralCase, String>{};
38+
39+
PluralsStatus consume({String key, ArbResource attributes, String value}) {
40+
final pluralCase = _getCase(key);
41+
42+
// normal item
43+
if (pluralCase == null) {
44+
if (_values.isNotEmpty) {
45+
final status = Completed(
46+
attributes: attributes,
47+
consumed: false,
48+
key: _key,
49+
values: Map.from(_values));
50+
_key = null;
51+
_attributes = null;
52+
_values.clear();
53+
return status;
54+
} else {
55+
_key = null;
56+
_attributes = null;
57+
return Skip();
58+
}
59+
}
60+
61+
// plural item
62+
final caseKey = _getCaseKey(key);
63+
64+
if (_key == caseKey) {
65+
// same plural
66+
_values[pluralCase] = value;
67+
return Consumed();
68+
} else if (_key == null) {
69+
// first plural
70+
_key = caseKey;
71+
_attributes = attributes;
72+
_values[pluralCase] = value;
73+
return Consumed();
74+
} else {
75+
// another plural
76+
PluralsStatus status;
77+
if (_values.isNotEmpty) {
78+
status = Completed(
79+
attributes: _attributes,
80+
consumed: true,
81+
key: _key,
82+
values: Map.from(_values));
83+
} else {
84+
status = Consumed();
85+
}
86+
_key = caseKey;
87+
_attributes = attributes;
88+
_values.clear();
89+
_values[pluralCase] = value;
90+
return status;
91+
}
92+
}
93+
94+
PluralsStatus complete() {
95+
if (_values.isNotEmpty) {
96+
return Completed(key: _key, attributes: _attributes, values: _values);
97+
}
98+
99+
return Skip();
100+
}
101+
102+
PluralCase _getCase(String key) {
103+
if (key.contains(_pluralSeparator)) {
104+
for (var plural in _pluralKeywords.keys) {
105+
if (key.endsWith('$_pluralSeparator$plural')) {
106+
return _pluralKeywords[plural];
107+
}
108+
}
109+
}
110+
return null;
111+
}
112+
113+
String _getCaseKey(String key) {
114+
return key.substring(0, key.lastIndexOf(_pluralSeparator));
115+
}
116+
}
117+
118+
class PluralsFormatter {
119+
static final String _countConst = 'count';
120+
121+
static final _icuPluralFormats = {
122+
PluralCase.zero: '=zero',
123+
PluralCase.one: '=one',
124+
PluralCase.two: '=two',
125+
PluralCase.few: 'few',
126+
PluralCase.many: 'many',
127+
PluralCase.other: 'other'
128+
};
129+
130+
static String format(Map<PluralCase, String> plural) {
131+
final builder = StringBuffer();
132+
builder.write('{$_countConst, plural,');
133+
plural.forEach((key, value) {
134+
if (value != null) {
135+
builder.write(
136+
' ${_icuPluralFormats[key]} {${value.replaceAll("\{#\}", "\{$_countConst\}")}}');
137+
}
138+
});
139+
builder.write('}');
140+
return builder.toString();
141+
}
142+
}

0 commit comments

Comments
 (0)