network_or_asset_loader 0.0.8 copy "network_or_asset_loader: ^0.0.8" to clipboard
network_or_asset_loader: ^0.0.8 copied to clipboard

A Flutter package that provides a network-based asset loader for easy_localization with smart fallback and caching capabilities.

NetworkOrAssetLoader #

A Flutter package that provides a network-based asset loader for easy_localization with smart fallback and caching capabilities.

Features #

  • Network-first loading: Downloads translation files from a remote server
  • Smart caching: Saves translations locally for offline access
  • Automatic fallback: Falls back to local cache or bundled assets when network is unavailable
  • Cache expiration: Configurable cache duration to ensure translations stay up-to-date
  • Connectivity awareness: Automatically detects network availability before attempting downloads
  • Timeout handling: Configurable network request timeout
  • Force refresh: Option to bypass cache and always fetch from the network
  • Source tracking: Optional callback to know where translations were loaded from
  • Custom HTTP client: Inject your own HTTP client for auth headers, interceptors, or testing

Getting Started #

1. Install dependencies #

Add the package to your pubspec.yaml:

dependencies:
  network_or_asset_loader: ^0.0.8
  easy_localization: ^3.0.8

Then run:

flutter pub get

2. Prepare local translation files #

Create JSON translation files in your assets folder. Each file should be named with the locale code (e.g. en.json, ar.json, fr.json) and contain a flat key-value map:

assets/
  translations/
    en.json
    ar.json
    fr.json

Example en.json:

{
  "app_title": "My App",
  "welcome_message": "Welcome!",
  "description": "This is a sample app."
}

3. Register assets in pubspec.yaml #

flutter:
  assets:
    - assets/translations/

4. Host translation files on your server #

Place the same JSON files on your remote server so they are accessible via URL. The localeUrl callback receives the locale name and must return the full URL to the JSON file. For example:

localeUrl: (String localeName) => 'https://yourdomain.com/translations/$localeName.json'

This will request:

  • https://yourdomain.com/translations/en.json
  • https://yourdomain.com/translations/ar.json
  • https://yourdomain.com/translations/fr.json

If your project uses an API endpoint class, you can reference it directly:

localeUrl: (String localeName) => '${ApiEndpoint.baseUrl}/$localeName.json'

5. Platform-specific setup #

Android

Add internet permission in android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

iOS

No extra setup needed — iOS allows outgoing network requests by default.

Usage #

Basic Setup #

import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:network_or_asset_loader/network_or_asset_loader.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();

  runApp(
    EasyLocalization(
      supportedLocales: const [Locale('en'), Locale('ar'), Locale('fr')],
      path: 'assets/translations',
      fallbackLocale: const Locale('en'),
      assetLoader: NetworkOrAssetLoader(
        localeUrl: (String localeName) =>
            'https://yourdomain.com/translations/$localeName.json',
        assetsPath: 'assets/translations',
      ),
      child: const MyApp(),
    ),
  );
}

Using Translations in Widgets #

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // These 3 lines are required for easy_localization to work
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('app_title'.tr())),
      body: Center(
        child: Text('welcome_message'.tr()),
      ),
    );
  }
}

Switching Locale at Runtime #

// Change to Arabic
await context.setLocale(const Locale('ar'));

// Change to French
await context.setLocale(const Locale('fr'));

Custom Timeout and Cache Duration #

NetworkOrAssetLoader(
  localeUrl: (String localeName) =>
      '${ApiEndpoint.baseUrl}/$localeName.json',
  assetsPath: 'assets/translations',
  // Wait up to 10 seconds for network response (default: 30s)
  timeout: const Duration(seconds: 10),
  // Re-fetch from server every 12 hours instead of every day (default: 1 day)
  localCacheDuration: const Duration(hours: 12),
)

Force Refresh (Bypass Cache) #

Set forceRefresh: true to always fetch from the network, ignoring any cached translations. Useful after an app update or when the user manually triggers a refresh:

NetworkOrAssetLoader(
  localeUrl: (String localeName) =>
      '${ApiEndpoint.baseUrl}/$localeName.json',
  assetsPath: 'assets/translations',
  forceRefresh: true,
)

Source Tracking (Debugging) #

Use the onSourceResolved callback to know where translations were loaded from. The callback receives the locale name and a TranslationSource enum:

NetworkOrAssetLoader(
  localeUrl: (String localeName) =>
      '${ApiEndpoint.baseUrl}/$localeName.json',
  assetsPath: 'assets/translations',
  onSourceResolved: (locale, source) {
    debugPrint('Locale "$locale" loaded from: $source');
    // source is one of:
    //   TranslationSource.cache        — valid local cache
    //   TranslationSource.network      — downloaded from server
    //   TranslationSource.expiredCache — expired cache used as fallback
    //   TranslationSource.asset        — bundled app assets
  },
)

Custom HTTP Client #

Inject your own http.Client to add authorization headers, custom certificates, or for testing:

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

final client = http.Client(); // or your custom client

NetworkOrAssetLoader(
  localeUrl: (String localeName) =>
      '${ApiEndpoint.baseUrl}/$localeName.json',
  assetsPath: 'assets/translations',
  httpClient: client,
)

Constructor Parameters #

Parameter Type Required Default Description
localeUrl String Function(String) Yes A function that receives the locale name (e.g. en, ar) and returns the full URL to the translation JSON file.
assetsPath String Yes Path to the bundled translation assets in your app (used as the final fallback).
timeout Duration No Duration(seconds: 30) Maximum time to wait for a network response before falling back.
localCacheDuration Duration No Duration(days: 1) How long cached translations are considered valid before re-fetching.
httpClient http.Client? No null Custom HTTP client for auth headers, interceptors, or testing. If not provided, a default client is used per request.
forceRefresh bool No false When true, skips cache and always fetches from the network first. Falls back to cache/assets on failure.
onSourceResolved void Function(String, TranslationSource)? No null Callback invoked after translations load, reporting the locale and the source used (cache, network, expiredCache, or asset).

How It Works #

The loader follows this priority order when loading translations:

1. Valid local cache exists?
   └─ Yes → Use cached translation ✅
   └─ No  ↓
2. Internet available?
   └─ Yes → Download from server, save to cache ✅
   └─ No  ↓
3. Expired local cache exists?
   └─ Yes → Use expired cache (better than nothing) ✅
   └─ No  ↓
4. Load from bundled assets ✅

This ensures the app always has translations available, whether the user is online or offline:

  • Online (first launch): Downloads from the server and caches locally.
  • Online (cache valid): Uses the local cache for instant loading — no network request.
  • Online (cache expired): Downloads fresh translations from the server.
  • Offline (cache available): Uses the cached translation regardless of age.
  • Offline (no cache): Falls back to the bundled asset files shipped with the app.

Additional Information #

Repository: https://github.com/wadihhannouch/wadnetworkassetloader

Issues: Please file issues on the GitHub issue tracker

Contributing: Contributions are welcome! Please feel free to submit a Pull Request.

1
likes
160
points
148
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter package that provides a network-based asset loader for easy_localization with smart fallback and caching capabilities.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

connectivity_plus, easy_localization, flutter, http, path_provider

More

Packages that depend on network_or_asset_loader