Search code examples
dartpackagelocalizationinternationalizationintl

How to use Intl in a dart only project?


I have a dart only package that does not dependence on Flutter, it contains common code and business logic code, some business logic will return the data that should be localized.

Let me say, I have a DataResponse<T> class In this dart package, and this dart package does not dependence on Flutter.

/// The current local info, 
/// about [Observable], this class can be listened, when the local is changed, it will notify the listeners.
class CurrentLocal extends Observable {
  CurrentLocal._();

  static CurrentLocal instance = CurrentLocal._();

  static const defaultLocale = "zh-CN";

  static const defaultUiLocale  = defaultLocale;

  /// the local for formatting strings, numbers, dates, currency etc..
  String _local = defaultCulture;

  /// language in UI
  String _uiLocal = defaultUiCulture;

  static String get local {
    return instance._local;
  }

  static String get uiLocal {
    return instance._uiLocal;
  }

  /// get current local
  String getLocal() => _local;

  /// get current UI local
  String getUiLocal() => _uiLocal;

  /// set the locals
  /// - [local]  the local for formatting
  /// - [uiLocal] the local for UI language
  void setLocal({String? local, String? uiLocal}) {
    if (local.stringIsNullOrWhitespace() && uiLocal.stringIsNullOrWhitespace()) {
      return;
    }
    bool flag = false;
    if (local != null && _local != local) {
      _local = local;
      flag = true;
    }
    if (uiLocal != null && _uiLocal != uiLocal) {
      _uiLocal = uiLocal;
      flag = true;
    }
    if (flag) {
      // Notify the listeners that the locals have been changed
      super.notifyObservers();
    }
  }
}

/// Response of a business logic.
/// [T] Response data, if there is no data, this will be `null`
@JsonSerializable(genericArgumentFactories: true)
class DataResponse<T> {
  /// operation result code
  String code;

  /// message of [code]
  String message;

  /// Response data, if there is no data, this will be `null`
  final T? data;

  DataResponse({required this.code, required this.message, this.data});

  factory DataResponse.fromJson(
          Map<String, dynamic> json, T Function(Object? json) fromJsonT) =>
      _$DataResponseFromJson(json, fromJsonT);

  Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
      _$DataResponseToJson(this, toJsonT);

  /// Unauthorized response
  static DataResponse<void> unauthorized = DataResponse(
    code: OperationCode.unauthorized,
    // This needs to be localized
    message: "require login",
  );

  /// 404 not found response
  static DataResponse<void> notFound = DataResponse(
    code: OperationCode.notFound,
    // This needs to be localized
    message: "resource not found",
  );

  /// system error in server end
  static DataResponse<void> systemError = DataResponse(
    code: OperationCode.systemError,
    // This needs to be localized
    message: "request failed",
  );
}

My entire dart package localization relies CurrentLocal class, use CurrentLocal.uiLocal and CurrentLocal.local for localized strings, request server end points. In class DataResponse<T> these message: "require login", message: "resource not found" and message: "request failed" need to be localized.

After search and reading the documents about Intl package, They are all about how to use it in Flutter project, and I am confusing, How do I use Intl in a dart package that doesn't dependence on Flutter? How to add ARB files and generate dart files from ARB? and use the generated dart files in DataResponse<T> to replace "require login" to a localized string?


Solution

  • package:intl and package:intl_translation are designed to be used in pure Dart applications as well. The readme and example at https://github.com/dart-lang/i18n/tree/main/pkgs/intl_translation should answer your question!