forked from cubetiq/cubetiq_dart_shared
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
a472156d22 | |||
3b2abdc030 | |||
34ce6f3e9b | |||
2b31d30228 | |||
5904c44789 | |||
51f7293977 | |||
635e3b49a1 | |||
5915aafb95 | |||
84c0e44b87 | |||
f555d68a29 | |||
57cded1c79 |
14
.drone.yml
Normal file
14
.drone.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
kind: pipeline
|
||||||
|
type: exec
|
||||||
|
name: default
|
||||||
|
platform:
|
||||||
|
os: darwin
|
||||||
|
arch: amd64
|
||||||
|
steps:
|
||||||
|
- name: flutter-dart-version
|
||||||
|
commands:
|
||||||
|
- flutter --version
|
||||||
|
- dart --version
|
||||||
|
- name: test
|
||||||
|
commands:
|
||||||
|
- dart test
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@ build/
|
|||||||
# Omit committing pubspec.lock for library packages; see
|
# Omit committing pubspec.lock for library packages; see
|
||||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
pubspec.lock
|
pubspec.lock
|
||||||
|
.dccache
|
@ -2,3 +2,9 @@
|
|||||||
|
|
||||||
- Configurable
|
- Configurable
|
||||||
- Text Formatter
|
- Text Formatter
|
||||||
|
|
||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
- Add translator provider
|
||||||
|
- Enhanced text formatter able to translate by options
|
||||||
|
- Fixed text formatter params and args for optional
|
||||||
|
7
example/cubetiq_functions.dart
Normal file
7
example/cubetiq_functions.dart
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import 'package:cubetiq/src/text/functions.dart';
|
||||||
|
import 'package:cubetiq/src/xlog/xlog.dart';
|
||||||
|
|
||||||
|
void main(List<String> args) {
|
||||||
|
XLog.debug(StringUtils.format(10.5555, 2));
|
||||||
|
XLog.debug(StringUtils.formatFromString('10.5555', 2));
|
||||||
|
}
|
@ -3,8 +3,8 @@ import 'package:cubetiq/text.dart';
|
|||||||
void main(List<String> args) {
|
void main(List<String> args) {
|
||||||
var text1 = 'Hello, {0}, then do this it by {1}!';
|
var text1 = 'Hello, {0}, then do this it by {1}!';
|
||||||
var text2 = 'Hello, {firstName}, then do this it by {lastName}!';
|
var text2 = 'Hello, {firstName}, then do this it by {lastName}!';
|
||||||
var result1 = TextFormatter(text1).format(['Sambo', 'Chea']);
|
var result1 = TextFormatter(text1).format(args: ['Sambo', 'Chea']);
|
||||||
var result2 = TextFormatter(text2).decorate({
|
var result2 = TextFormatter(text2).decorate(params: {
|
||||||
'firstName': 'Sambo',
|
'firstName': 'Sambo',
|
||||||
'lastName': 'Chea',
|
'lastName': 'Chea',
|
||||||
});
|
});
|
||||||
|
36
example/cubetiq_translator_example.dart
Normal file
36
example/cubetiq_translator_example.dart
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import 'package:cubetiq/text.dart';
|
||||||
|
import 'package:cubetiq/i18n_translator.dart';
|
||||||
|
|
||||||
|
void main(List<String> args) {
|
||||||
|
var text = 'Your name is {name}!';
|
||||||
|
// Before set provider
|
||||||
|
var result = StringUtils.decorator(text, translate: true, params: {
|
||||||
|
'name': 'Sambo Chea',
|
||||||
|
});
|
||||||
|
print('Result Before => $result');
|
||||||
|
|
||||||
|
TranslatorFactory.setProvider(TranslatorProviderExample());
|
||||||
|
|
||||||
|
// After set provider
|
||||||
|
result = StringUtils.decorator(text, translate: true, params: {
|
||||||
|
'name': 'Sambo Chea',
|
||||||
|
});
|
||||||
|
print('Result After => $result');
|
||||||
|
}
|
||||||
|
|
||||||
|
class TranslatorProviderExample implements TranslatorProvider {
|
||||||
|
@override
|
||||||
|
bool hasKey(String key) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String translate(String key,
|
||||||
|
{Map<String, dynamic>? params, String? fallback}) {
|
||||||
|
if (key == 'Your name is {name}!') {
|
||||||
|
return 'ឈ្មោះរបស់អ្នកគឺ {name}!';
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
91
example/my_cart_example.dart
Normal file
91
example/my_cart_example.dart
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import 'package:cubetiq/model.dart';
|
||||||
|
|
||||||
|
void main(List<String> args) {
|
||||||
|
MyCart.addCart(
|
||||||
|
Cart(id: 1, name: 'Apple', qty: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
MyCart.show();
|
||||||
|
|
||||||
|
MyCart.addCart(
|
||||||
|
Cart(id: 1, name: 'Apple', qty: 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
MyCart.show();
|
||||||
|
|
||||||
|
MyCart.inc(1, qty: 2);
|
||||||
|
|
||||||
|
MyCart.show();
|
||||||
|
|
||||||
|
MyCart.dec(1, qty: 4);
|
||||||
|
|
||||||
|
MyCart.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Cart extends BaseModel<Cart> {
|
||||||
|
final int id;
|
||||||
|
final String? name;
|
||||||
|
double qty;
|
||||||
|
|
||||||
|
Cart({this.id = -1, this.name, this.qty = 0});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Cart fromMap(Map<String, dynamic> map) {
|
||||||
|
return Cart(
|
||||||
|
id: map['id'],
|
||||||
|
name: map['name'],
|
||||||
|
qty: map['qty'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'name': name,
|
||||||
|
'qty': qty,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyCart {
|
||||||
|
static final Map<int, Cart> carts = {};
|
||||||
|
|
||||||
|
static void inc(int id, {double qty = 1}) {
|
||||||
|
if (carts.containsKey(id)) {
|
||||||
|
carts[id]!.qty += qty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dec(int id, {double qty = 1}) {
|
||||||
|
if (carts.containsKey(id)) {
|
||||||
|
carts[id]!.qty -= qty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addCart(Cart cart) {
|
||||||
|
if (carts.containsKey(cart.id)) {
|
||||||
|
carts[cart.id]!.qty += cart.qty;
|
||||||
|
} else {
|
||||||
|
carts[cart.id] = cart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void removeCart(Cart cart) {
|
||||||
|
if (carts.containsKey(cart.id)) {
|
||||||
|
carts.remove(cart.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show() {
|
||||||
|
var data = carts.map((key, value) => MapEntry(key, value));
|
||||||
|
var json = data.map((key, value) => MapEntry(key, value.toJson()));
|
||||||
|
var model = json.map((key, value) => MapEntry(key, Cart().fromJson(value)));
|
||||||
|
print('================ Map =================');
|
||||||
|
print('$data');
|
||||||
|
print('================ Json =================');
|
||||||
|
print('$json');
|
||||||
|
print('================ Model =================');
|
||||||
|
print('$model');
|
||||||
|
}
|
||||||
|
}
|
4
lib/i18n_translator.dart
Normal file
4
lib/i18n_translator.dart
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
library i18n_translator;
|
||||||
|
|
||||||
|
export 'src/i18n/translator_provider.dart';
|
||||||
|
export 'src/i18n/translator_factory.dart';
|
3
lib/model.dart
Normal file
3
lib/model.dart
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
library model;
|
||||||
|
|
||||||
|
export 'src/model/base.dart';
|
34
lib/src/i18n/translator_factory.dart
Normal file
34
lib/src/i18n/translator_factory.dart
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import 'translator_provider.dart';
|
||||||
|
|
||||||
|
/// Translate Factory
|
||||||
|
///
|
||||||
|
/// @author sombochea
|
||||||
|
/// @since 1.0.0
|
||||||
|
class TranslatorFactory {
|
||||||
|
static TranslatorProvider? _provider;
|
||||||
|
static void setProvider(TranslatorProvider provider) {
|
||||||
|
_provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hasProvider() => _provider != null;
|
||||||
|
|
||||||
|
static bool hasKey(String key) {
|
||||||
|
if (hasProvider()) {
|
||||||
|
return _provider!.hasKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String translate(
|
||||||
|
String key, {
|
||||||
|
Map<String, dynamic>? params,
|
||||||
|
String? fallback,
|
||||||
|
}) {
|
||||||
|
if (hasProvider()) {
|
||||||
|
return _provider!.translate(key, params: params, fallback: fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback ?? key;
|
||||||
|
}
|
||||||
|
}
|
9
lib/src/i18n/translator_provider.dart
Normal file
9
lib/src/i18n/translator_provider.dart
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/// Translate Provider
|
||||||
|
///
|
||||||
|
/// @author sombochea
|
||||||
|
/// @since 1.0.0
|
||||||
|
abstract class TranslatorProvider {
|
||||||
|
bool hasKey(String key);
|
||||||
|
String translate(String key,
|
||||||
|
{Map<String, dynamic>? params, String? fallback});
|
||||||
|
}
|
33
lib/src/model/base.dart
Normal file
33
lib/src/model/base.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
abstract class BaseModel<T> {
|
||||||
|
BaseModel();
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap();
|
||||||
|
|
||||||
|
T fromMap(Map<String, dynamic> map);
|
||||||
|
|
||||||
|
T fromJson(String json) {
|
||||||
|
return fromMap(decode(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return toMap().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(this, other)) return true;
|
||||||
|
|
||||||
|
return other is BaseModel && other.toMap() == toMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => toMap().hashCode;
|
||||||
|
|
||||||
|
String toJson() => encode(toMap());
|
||||||
|
|
||||||
|
dynamic decode(String json) => jsonDecode(json);
|
||||||
|
String encode(dynamic json) => jsonEncode(json);
|
||||||
|
}
|
@ -7,10 +7,11 @@ extension StringExtensionOnNonull on String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension StringExtensionOnNullable on String? {
|
extension StringExtensionOnNullable on String? {
|
||||||
String? textFormat(List<dynamic> args) => StringUtils.textFormat(this, args);
|
String? textFormat({List<dynamic>? args, bool translate = false}) =>
|
||||||
|
StringUtils.textFormat(this, args: args, translate: translate);
|
||||||
|
|
||||||
String? decorator(Map<String, dynamic> params) =>
|
String? decorator({Map<String, dynamic>? params, bool translate = false}) =>
|
||||||
StringUtils.decorator(this, params);
|
StringUtils.decorator(this, params: params, translate: translate);
|
||||||
|
|
||||||
bool get isBlank {
|
bool get isBlank {
|
||||||
if (this == null) return true;
|
if (this == null) return true;
|
||||||
@ -32,4 +33,8 @@ extension StringExtensionOnNullable on String? {
|
|||||||
bool get isNullOrEmptyOrBlank => StringUtils.isNullOrEmptyOrBlank(this);
|
bool get isNullOrEmptyOrBlank => StringUtils.isNullOrEmptyOrBlank(this);
|
||||||
|
|
||||||
bool get isEqualsIgnoreCase => StringUtils.equalsIgnoreCase(this, this);
|
bool get isEqualsIgnoreCase => StringUtils.equalsIgnoreCase(this, this);
|
||||||
|
|
||||||
|
String toPrecision([int precision = 2]) {
|
||||||
|
return StringUtils.formatFromString(this, precision);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,26 @@ class StringUtils {
|
|||||||
return n.toStringAsFixed(n.truncateToDouble() == n ? precision : precision);
|
return n.toStringAsFixed(n.truncateToDouble() == n ? precision : precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format number from String with precision
|
||||||
|
static String formatFromString(String? text, [int precision = 2]) {
|
||||||
|
text ??= '0.0';
|
||||||
|
var n = double.parse(text);
|
||||||
|
return n.toStringAsFixed(n.truncateToDouble() == n ? precision : precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Text formatter with custom args
|
||||||
|
static TextFormatter textFormatter(String? text, {bool translate = false}) =>
|
||||||
|
TextFormatter(text).translate(translate: translate);
|
||||||
|
|
||||||
/// Text format with custom args
|
/// Text format with custom args
|
||||||
static String? textFormat(String? text, List<dynamic> args) =>
|
static String? textFormat(String? text,
|
||||||
TextFormatter(text).format(args);
|
{List<dynamic>? args, bool translate = false}) =>
|
||||||
|
textFormatter(text, translate: translate).format(args: args);
|
||||||
|
|
||||||
/// Text decorator with custom key/value params
|
/// Text decorator with custom key/value params
|
||||||
static String? decorator(String? text, Map<String, dynamic> params) =>
|
static String? decorator(String? text,
|
||||||
TextFormatter(text).decorate(params);
|
{Map<String, dynamic>? params, bool translate = false}) =>
|
||||||
|
textFormatter(text, translate: translate).decorate(params: params);
|
||||||
|
|
||||||
static String? asLowerCaseThenTrim(String? text) =>
|
static String? asLowerCaseThenTrim(String? text) =>
|
||||||
text?.toLowerCase().trim();
|
text?.toLowerCase().trim();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:cubetiq/i18n_translator.dart';
|
||||||
|
|
||||||
/// Text Formatter
|
/// Text Formatter
|
||||||
///
|
///
|
||||||
/// @author sombochea
|
/// @author sombochea
|
||||||
@ -9,12 +11,20 @@ class TextFormatter {
|
|||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? format(List<dynamic> args) {
|
TextFormatter translate({bool translate = true}) {
|
||||||
|
if (translate && text != null && text?.isNotEmpty == true) {
|
||||||
|
text = TranslatorFactory.translate(text!);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? format({List<dynamic>? args}) {
|
||||||
if (text == null) {
|
if (text == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.isEmpty) {
|
if (args == null || args.isEmpty == true) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,12 +41,12 @@ class TextFormatter {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? decorate(Map<String, dynamic> params) {
|
String? decorate({Map<String, dynamic>? params}) {
|
||||||
if (text == null) {
|
if (text == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.isEmpty) {
|
if (params == null || params.isEmpty == true) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,14 @@ class XLog {
|
|||||||
logger.success(data, args);
|
logger.success(data, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void log(String prefix, dynamic data, [List? args]) {
|
||||||
|
logger.show(XLogType.DEBUG, prefix, data, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show(XLogType type, String prefix, dynamic data, [List? args]) {
|
||||||
|
logger.show(type, prefix, data, args);
|
||||||
|
}
|
||||||
|
|
||||||
static void info(dynamic data, [List? args]) {
|
static void info(dynamic data, [List? args]) {
|
||||||
logger.info(data, args);
|
logger.info(data, args);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ abstract class XLogProvider {
|
|||||||
if (args == null || args.isEmpty) {
|
if (args == null || args.isEmpty) {
|
||||||
content = data;
|
content = data;
|
||||||
} else {
|
} else {
|
||||||
content = StringUtils.textFormat(data, args) ?? 'null';
|
content = StringUtils.textFormat(data, args: args) ?? 'null';
|
||||||
}
|
}
|
||||||
|
|
||||||
var text = '[$type] ${nowToString()}: $prefix => $content'.trim();
|
var text = '[$type] ${nowToString()}: $prefix => $content'.trim();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: cubetiq
|
name: cubetiq
|
||||||
description: CUBETIQ Dart Shared is functions, utils, and extensions for developers.
|
description: CUBETIQ Dart Shared is functions, utils, and extensions for developers.
|
||||||
version: 1.0.0
|
version: 1.0.1
|
||||||
homepage: https://www.cubetiqs.com
|
homepage: https://www.cubetiqs.com
|
||||||
repository: https://git.cubetiqs.com/CUBETIQ/cubetiq_dart_shared.git
|
repository: https://git.cubetiqs.com/CUBETIQ/cubetiq_dart_shared.git
|
||||||
|
|
||||||
|
37
test/cubetiq_i18n_test.dart
Normal file
37
test/cubetiq_i18n_test.dart
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import 'package:cubetiq/i18n_translator.dart';
|
||||||
|
import 'package:cubetiq/src/xlog/xlog.dart';
|
||||||
|
import 'package:cubetiq/text.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test('test translate function', () {
|
||||||
|
var text1 = 'Hello, my name is {0}!';
|
||||||
|
var result1 = TextFormatter(text1).translate().format(args: ['Sambo']);
|
||||||
|
XLog.success(result1);
|
||||||
|
|
||||||
|
expect('Hello, my name is Sambo!', result1);
|
||||||
|
|
||||||
|
TranslatorFactory.setProvider(TranslatorProviderExample());
|
||||||
|
|
||||||
|
result1 = TextFormatter(text1).translate().format(args: ['Sambo']);
|
||||||
|
XLog.success(result1);
|
||||||
|
expect('ឈ្មោះរបស់អ្នកគឺ Sambo!', result1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class TranslatorProviderExample implements TranslatorProvider {
|
||||||
|
@override
|
||||||
|
bool hasKey(String key) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String translate(String key,
|
||||||
|
{Map<String, dynamic>? params, String? fallback}) {
|
||||||
|
if (key == 'Hello, my name is {0}!') {
|
||||||
|
return 'ឈ្មោះរបស់អ្នកគឺ {0}!';
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,10 @@ import 'package:test/test.dart';
|
|||||||
void main() {
|
void main() {
|
||||||
test('text formatter function format', () {
|
test('text formatter function format', () {
|
||||||
var text1 = 'Hello, {0}!';
|
var text1 = 'Hello, {0}!';
|
||||||
var result1 = TextFormatter(text1).format(['Sambo']);
|
var result1 = TextFormatter(text1).format(args: ['Sambo']);
|
||||||
|
|
||||||
var text2 = 'Hello, {name}!';
|
var text2 = 'Hello, {name}!';
|
||||||
var result2 = TextFormatter(text2).decorate({'name': 'Chea'});
|
var result2 = TextFormatter(text2).decorate(params: {'name': 'Chea'});
|
||||||
|
|
||||||
expect('Hello, Sambo!', result1);
|
expect('Hello, Sambo!', result1);
|
||||||
expect('Hello, Chea!', result2);
|
expect('Hello, Chea!', result2);
|
||||||
|
Loading…
Reference in New Issue
Block a user