Code Monkey home page Code Monkey logo

laravel-js-localization's Introduction

laravel-js-localization

Build Status Scrutinizer Code Quality Code Coverage Total Downloads

Simple, ease-to-use and flexible package for the Laravel web framework. Allows you to use localized messages of the Laravel webapp (see resources/lang directory) in your Javascript code. You may easily configure which messages you need to export.

⚠️ Looking for a new maintainer. Please contact me if you are interested.

Branches

Laravel Branch
8 laravel-8
7 laravel-7
6 laravel-6
5.8 laravel-5.8
5.0 - 5.7 laravel-5 (end of life)

Installation

Add the following line to the require section of your Laravel webapp's composer.json file:

    "require": {
        "andywer/js-localization": "dev-laravel-6"      // see table above
    }

Run composer update to install the package.

Finally add the following line to the providers array of your app/config/app.php file:

    'providers' => [
        /* ... */
        JsLocalization\JsLocalizationServiceProvider::class
    ]

Configuration

Run php artisan vendor:publish first. This command copies the package's default configuration to config/js-localization.php.

You may now edit this file to define the messages you need in your Javascript code. Just edit the messages array in the config file.

Example (exports all reminder messages):

<?php

return [
    // Set the locales you use
    'locales' => ['en'],

    // Set the keys of the messages you want to use in javascript
    'messages' => [
        'passwords' => [
            'password', 'user', 'token'
        ]
    ],

    /*
     * in short:
     * 'messages' => ['passwords']
     *
     *
     * you could also use:
     *
     * 'messages' => [
     *     'passwords.password',
     *     'passwords.user',
     *     'passwords.token'
     * ]
     */
     
    // Set the keys of config properties you want to use in javascript.
    // Caution: Do not expose any configuration values that should be kept privately!
    'config' => [
        'app.debug'
    ],
     
    // Disables the config cache if set to true, so you don't have to run `php artisan js-localization:refresh`
    // each time you change configuration files.
    // Attention: Should not be used in production mode due to decreased performance.
    'disable_config_cache' => false,

    // Split up the exported messages.js file into separate files for each locale.
    // This is to ensue faster loading times so one doesn't have to load translations for _all_ languages.
    'split_export_files' => true,
];

Important:

The messages configuration will be cached when the JsLocalizationController is used for the first time. After changing the messages configuration you will need to call php artisan js-localization:refresh to refresh that cache. That also affects the config properties you export to javascript, since they are cached, too.

Usage

The translation resources for JavaScript can either be served by your Laravel app at run-time or they can be pre-generated as static JavaScript files, allowing you to serve them straight from your web server or CDN or to be included in your build process.

Run-time generation

You just need to add the necessary <script> tags to your layout. Here is an example blade view:

@include('js-localization::head')
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Test view</title>
        @yield('js-localization.head')
    </head>
    <body>
        <p>
            Here comes a translated message:
            <script type="text/javascript">
                document.write( Lang.get('reminder.user') );
            </script>
        </p>
    </body>
</html>

Remember it's best to not put the @yield('js-localization.head') in the <head> as it contains the <script> tag shipping the frontend part of this package. It's best practice to put it at the end of the <body>, but before other <script> tags. The example above simply includes it in the head, since it's the simplest form to use it.

Static generation

For increased performance it is possible to generate static JavaScript files with all of your generated strings. These files can either be served directly as static files, or included as a part of your frontend asset build process.

To specify the output directory for the assets, just set the $storage_path string in your config/js-localization.php file accordingly (see Configuration).

    /*
    |--------------------------------------------------------------------------
    | Define the target to save the exported messages to
    |--------------------------------------------------------------------------
    |
    | Directory for storing the static files generated when using file storage.
    |
    */

    'storage_path' => public_path('vendor/js-localization/'),

The files can then be generated using the artisan command:

php artisan js-localization:export

This will generate two files in your target directory:

  • messages.js contains your translation strings
  • config.js contains your exported config values

If you want to automatically split up the messages.js file into separate .js files for each locale, you can set the following to true in your config/js-localization.php config file:

    'split_export_files' => true,

This will in turn also generate the following file(s) in your target directory:

  • lang-{locale}.js contains one language's translation strings, if the split_export_files config option is set to true

Remember that the files needs to be regenerated using php artisan js-localization:export every time any translation strings are edited, added or removed.

Features

You may use Lang.get(), Lang.has(), Lang.choice(), Lang.locale() and trans() (alias for Lang.get()) in your Javascript code. They work just like Laravel's Lang facade. Additionally, you are able to pass configuration properties to your Javascript code as well. There is Config.get() in Javascript, too. Configure which config properties to pass to the client using the config field in config/js-localization.php. Attention: Do not export any security-critical properties like DB credentials or similar, since they would be visible to anyone using your application!

Variables in messages are supported. For instance: "This is my test string for :name.".

Pluralization is also supported, but does not care about the locale. It only uses the English pluralization rule ("singular text|plural text"). More complex pluralization quantifiers are not yet supported.

Service providers

Assume you are developing a laravel package that depends on this javascript localization features and you want to configure which messages of your package have to be visible to the JS code.

Fortunately that's pretty easy. Just listen to the JsLocalization.registerMessages event and use the JsLocalization\Facades\JsLocalizationHelper::addMessagesToExport() method. Like so:

<?php

use Illuminate\Support\ServiceProvider;
use JsLocalization\Facades\JsLocalizationHelper;

class MyServiceProvider extends ServiceProvider
{
    /* ... */

    public function register()
    {
        Event::listen('JsLocalization.registerMessages', function()
        {
            JsLocalizationHelper::addMessagesToExport([
                // list the keys of the messages here, similar
                // to the 'messages' array in the config file
            ]);
        });
    }

    /* ... */
}

License

This software is released under the MIT license. See license.

laravel-js-localization's People

Contributors

alexwijn avatar andywer avatar bytestream avatar carestad avatar dazzy avatar fjoho avatar matthijsvdorp avatar mellievt avatar mjpvandenberg avatar natharduini avatar sintemaa avatar skullbock avatar upwardprocess avatar volantwish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

laravel-js-localization's Issues

Add config option for not encoding as html entities

First of all, thanks for this great package!

I'm having a problem with the html entity representations of German Umlauts (äöü) in javascript. For example bestätige is being encoded as best&auml;tige. This does not work when I pass the string to a plugin that then sets the text e.g. with jQuery's .text().

Could you add an option to not encode special characters and just keep everything utf-8?

Static generation getting started

I've got a problem with static generation. How I add in the ?

without use @include('js-localization::head') and @yield('js-localization.head')

I use :export command
The messages.js's file is updated but it is don't use in live

The artisan commands does not work with Laravel 5.5

The export and refresh artisan commands do not work with Laravel 5.5 since it now requires a handle function instead of a fire function on the commands.

Method JsLocalization\Console\ExportCommand::handle() does not exist

Country config values

In our project we require some country-specific config values to be exported, ie. countries.en.currency. As it is now, we need to add the config value to the $config setting for each country, which is cumbersome and error-prone, even more so when we add a new country.
Right now we've fixed this by adding an additional config array with all theses values. When we generate the config output we just iterate through all values of the $locales array, for each value in this country config array.
Others might have similar needs, and it seems natural that a localization package can work with localized data :-)
Would you accept a PR on this?
I'm thinking:

  1. Add a new $countries_config config array
  2. Iterate through the $countries_config array for each value in $locales, when generating the json output JsLocalization\Caching\ConfigCachingService::createConfigJson()

Lang.get does not work for nested objects.

Lang.get in public/js/localization.js does not work with nested objects.

Steps to reproduce the problem
Step 1: Create a language file like so...

return [
    "a" => [
        "b" => "hello"
    ]
]

Step 2: Call Lang.get('a.b')

Expected behavior
Step 2 should return "hello".

Actual behavior
Step 2 returns "a.b".

Empty Messages

I am using Laravel 5.3.

I installed and set up the package as instructed.

However, no translations are available. Browsing to /js-localization/messages shows Lang.addMessages({"fr":[],"en":[]});

Anything I still have to do in addition to what is said in the README?

My paths look like e.g. ..lang/en/auth.php. Standard, I assume.

Maybe I should say that I also have mcamara's localization package installed.

[Suggestion] Asterix to select all locales which is currently in use, and maybe a selector for all files with a filename in those locales

I haven't tested this yet, as I just stumbled upon this package, and I'll start using it tomorrow.

Anyways, It'd be smart if I could just write locale: * to get all locales that I have in my resources/lang folder.

Eg. I want all locales of a single file, which might be called js-lang.php or something like that.

It would allow me to put the locales in there which I need in JS, but also have them in all locales in JS.

Do you get what I am trying to say? otherwise I will elaborate tomorrow :)

[feature] default language keys when missing in a split_export_files

Hi and thanks a lot for this great and useful package.

It could be nice to have an option that make generation of split_export_files merging default language keys when they are missing in a language file.

For example with those languages keys in resources/langs :

  • en [default]
    • foo
    • bar
  • fr
    • foo

we could navigate in language "fr" and displaying the "en [default]" value in place of the key path.

Also it make Javascript translation works like the Php Laravel side with a default language value when a language missing a key.

I Hope to be clear enough ... I'm not sure :-)

It seems it's writing locale twice

I follow the indications but i hasn't work, I've reviewed the code for a while and I think tha the problem is when the plugin is creating the messages file, it writes twice the locale as you can see in the picture

image

Unable to get translation to work (question on how this supposed to work)

I am asking this because there is no explanation/example on how it actually works

I am using laravel 5.7

line in composer "andywer/js-localization": "dev-laravel-5"

in my messages.php I have 'test' => 'frtest' in lang/fr_FR folder

in js-localization.php file I have :
'locales' => [ 'en_US', 'en_AU', 'fr_FR', 'ja_JP' ],
'messages' => [ 'test' ],
'disable_config_cache' => true,
the rest are all default

in my js file I am trying to use Lang.get( 'messages.test' ) or I tried Lang.get( 'test' )

This just returns the key messages.test or test

I don't know what I am doing wrong, I couldn't find any full examples on how this works so now I am stuck. Can anyone tell me how this thing actually works?

Use toString() in localization.js?

The applyReplacements function in resources/js/localization.js has some minor changes in the following commit:

2ca47fe#diff-a3095dfb9ac91acd2bb0a74831fa7c7d

These changes are using string functions like toUpperCase() without using toString() on the value first which results in passing numeric values as translation parameters to be broken.

For example, using the following code results in a TypeError: i.toUpperCase is not a function error:

Lang.get('general.number_of_rows', {number: 10})

I would suggest adding toString() before using any string functions to make the JS library backward compatible.

Multilanguage support

Hello,

I'm writing multilanguage app and i can' get multilanguage to work. Is that package support it? What do i have to do to get this work?

Make translations importable at build-time?

I don't generate my frontend javascript html pages with PHP/Laravel, so I can't include the templates to pull translations as additional http requests. I could still include them manually, in theory, but ideally, I would like to import them directly into my application at build-time, with gulp (and browserify in my case). It looks like this is already 90% of the way there, I think it just needs a command to export the cached translation files to stdout instead of an http response, and then a quick gulp wrapper could be written, or even better, an extension to Laravel Elixir.

Also, everything should be exportable as an es6 module so that it doesn't pollute the global/window scope!

js-localization/messages not generated

I did the following :

composer require andywer/js-localization:dev-laravel-5 -vvv
composer update
php artisan vendor:publish

changed the config file to :

'messages' => ['services']

Then

php artisan js-localization:refresh

and I've added:

@include('js-localization::head')
@yield('js-localization.head')

But still message javascript file not generated and document.write( Lang.get('services.user') ) returns error.

Did I miss anything?

Strange localization behaviours

Not sure if this is related to Laravel 5.1, but with both the laravel-5 and develop branch I'm experiencing this behaviour:

Whatever locale I set in my frontend controller with App::setLocale('xx'):

  • non-JS labels are displayed correctly according to the locale set with App::setLocale
  • but js-localization is always set according to the browser (!) language.

I debugged by logging the Lang::locale() in both my frontend controller and in the JsLocalizationController in getMessagesJson() method, and the result is as mentioned above: Lang:locale() in JsLocalizationController is not influenced by the App::setLocale() value set in frontend controller, but always seems to depend on the browser's language. When I change the browser language, that value changes accordingly.

Any idea?

Tag version

Could you please tag versions of the package so we can lock to a specific version in our composer dependencies? For example, we are unable to use this commit currently as our PHP requirements are >=7.2.0 to match Laravel 6.x.
54e713e#diff-b5d0ee8c97c7abd7e3fa29b9a27d1780

Translation in configuration

In my application configuration I have set a variable, which I'd like to have in my js-localization as well. It looks like the following:

Config (mysite.php):

return array(
    'products'   => 'Products'
);

In my language file (products.php) I have the following entry:

'products'  => Config::get('mysite.products')

In the packages configuration I have:

'messages' => array(
    'products'  => array(
        'products'
    ),
)

After I run:

php artisan js-localization:refresh

I do get an entry in the messages file, but it does not look like: "products.products" : "Products" but it shows: "products.products" : "products.products"


I think this happens because the package can't read from the configuration, or something. Can't figure out why this does not work. Is this an issue or am I doing something wrong?

To clarify - the codebase will be used on multiple sites, where Products can also be named Items (or whatever). Perhaps I'm overthinking this and there might be a better way in doing such a thing, if that is the case I'd love to know how :)

No support for content Tags

If you are using content or escaped content tags (such as [[ ]] [!! !!]), plugin has no support for them.
It was neccesary to change it manually in the views\head.blade.php

No support for content Tags

If you are using content or escaped content tags (such as [[ ]] [!! !!]), plugin has no support for them.
It was neccesary to change it manually in the views\head.blade.php

Laravel 7 support

I'd like to start using this package in my new Laravel 7.4 project, but this version is not supported

Upgrade to laravel 5

Hi !
I've been using your module a lot on my laravel 4.2 project !

We are now upgrading to Laravel 5.1 and having an issue with the cache.
Everything else is correctly upgrated and operational but when I run php artisan js-localization:refresh I get the following error message:

Refreshing the message cache...


  [InvalidArgumentException]
  Cache store [] is not defined.

First I thought it was an installation issue. I re-installed everything from scratch following the laravel doc guide. i doubled check every configuration etc... But I'm still having this issue.

It doesn't seem to be a laravel-js-localization bug because when I try to use cache in my own code I have the same bug ! But I'm so desperately in need for a solution that I also post here for any hint..

Does anyone already faced this kind of bug or have any idea of what to try ?

How to import translations ?

How to import translations from resources/lang/en/all.php ?

Lang.addMessages({ "en": { "partnership": "Create report", } }); Lang.setLocale("en"); console.log(Lang.get('partnership'));

Permission denied error on js-localization:refresh

About a week ago I installed this package in a project we're working on, and everything went fine. I added variables to the language files, followed the steps in the documentation and everything was displayed properly.
After that I pushed everything to our git repository so my colleagues could pull the changes and apply them to their environments. That's where the problems start. Some of the variables aren't in their js-localization/messages file and thus not displayed.
We've tried running php artisan js-localization:refresh but that causes a permission denied error:

[ErrorException]
  file_put_contents(/opt/caret/docroot/<project>/storage/framework/cache/b3/46/b3466d72f5ce06bd232850584bf9060f5446e55f): failed to open stream: Permission denied

That is the cached version of the js-localization:refresh file:

Lang.addMessages(
{
en: {
ClickAdmin::backend.js.something_went_wrong: "Er is iets fout gegaan",
ClickAdmin::backend.js.ok: "OK",
ClickAdmin::backend.js.emptytable: "Geen gegevens aanwezig in de tabel",
ClickAdmin::backend.js.info: "Totaal :attribute resultaten",
ClickAdmin::backend.js.infoempty: "Geen data om weer te geven",
ClickAdmin::backend.js.lengthmenu: "Toon :attribute resultaten",
ClickAdmin::backend.js.loadingrecords: "Een moment geduld a.u.b. - bezig met laden...",
ClickAdmin::backend.js.zerorecords: "Geen data om weer te geven",
ClickAdmin::backend.js.delete_are_you_sure: "Weet je zeker dat je :attribute wilt verwijderen?",
ClickAdmin::backend.js.delete_cancel: "Annuleren",
ClickAdmin::backend.js.delete_confirm: "Verwijderen",
ClickAdmin::backend.js.mobile_visitors: "Mobiele bezoekers",
ClickAdmin::backend.js.last_24_hours: "Laatste 24 uur",
ClickAdmin::backend.js.last_7_days: "Laatste 7 dagen",
ClickAdmin::backend.js.last_31_days: "Laatste 31 dagen",
ClickAdmin::backend.js.page_views: "Paginaweergaven",
ClickAdmin::backend.js.visitors: "Bezoekers",
ClickAdmin::backend.js.analytics_not_installed: "Analytics is niet ingesteld voor deze website, of niet gekoppeld aan deze admin. Heb je interesse voor Google Analytics? Neem contact op via <a href="mailto:[email protected]">[email protected]</a>",
ClickAdmin::backend.js.jan: "jan",
ClickAdmin::backend.js.feb: "feb",
ClickAdmin::backend.js.mar: "mar",
ClickAdmin::backend.js.apr: "apr",
ClickAdmin::backend.js.mei: "mei",
ClickAdmin::backend.js.jun: "jun",
ClickAdmin::backend.js.jul: "jul",
ClickAdmin::backend.js.aug: "aug",
ClickAdmin::backend.js.sep: "sep",
ClickAdmin::backend.js.okt: "okt",
ClickAdmin::backend.js.nov: "nov",
ClickAdmin::backend.js.dec: "dec",
ClickAdmin::backend.js.new_visitors: "Nieuwe bezoekers",
ClickAdmin::backend.js.returning_visitors: "Terugkerende bezoekers",
ClickAdmin::backend.js.device_desktop: "Desktop",
ClickAdmin::backend.js.device_mobile: "Mobile",
ClickAdmin::backend.js.device_tablet: "Tablet",
ClickAdmin::backend.js.selected_image: "Geselecteerde afbeelding",
ClickAdmin::backend.js.selected_document: "Geselecteerd document",
ClickAdmin::backend.js.files_selected: "Bestanden geselecteerd",
ClickAdmin::backend.js.are_you_sure: "Weet je zeker dat je dit bestand wilt verwijderen?",
ClickAdmin::backend.js.cannot_be_undone: "Deze actie kan niet worden teruggedraaid. Eventuele niet opgeslagen wijzigingen worden niet opgeslagen.",
ClickAdmin::backend.js.image_too_small_title: "Afbeelding te klein",
ClickAdmin::backend.js.image_too_small_text: "De afbeelding is te klein, probeer de uitsnede groter te maken.",
ClickAdmin::backend.js.minimal_sizes: "Minimale grootte(s):"
}
)```

Is this something that's caused by the package?
Maybe when saving the cache file?

Lang.choice() doesn't parse :count

On Laravel, Lang::choice() will parse :count, but Lang.choice() doesn't:

Lang::choice('schedule.x-posts-filtered', 2)
// => "2 postes filtrés"

Lang.choice('schedule.x-posts-filtered', 2)
// => ":count postes filtrés"

Not ideal, but it can be countered with:

Lang.choice('schedule.x-posts-filtered', 2, {count: 2})
// => "2 postes filtrés"

Lang.get("") returns whole object of translations

When adding an empty string to Lang.get(), it returns the whole translation object for your locale.

Would expect it to just return an empty string?

E.g. Lang.get("") => { key1: "foo" ... } (object)
Expected: Lang.get("") => "" (string)

I know there is code that checks if the first argument to Lang.get() is the key name for one of the translation files and returns that object, but I am not sure if this is the intended behaviour.

Simple fix/PR would probably just be a if (key === '') { return '' }. Can provide if bug is confirmed.

Disable cache expiry

We use js-localization (thanks :-)) in a Laravel 5.1 project, and it's working really well.

We do have one issue, though, I believe it's to do with the cache.
Some of the longest running processes on our site is /js-localization/messages . My guess is that it's because the message cache expires and the messages json is rebuilt. Is it possible to disable the cache expiry and only have the messages rebuilt using the artisan command? Or did I misunderstand what is actually going on in that step? :-)

1 command to rule them all

As discussed in this issue, adding a translation for JS requires these steps:

  1. adding the translation
  2. registering the translation for js
  3. refreshing the js translation cache

Which isn't a problem when adding one translation, but during active development this can become a bit verbose.

Have you used the philo/laravel-translate package? It takes care of step 1 for you. You do
php artisan translate:add group key
Then it asks you for each translation one by one and refreshes the appropriate files for you.

So a command that runs translate:add, parses and rewrites the js localization config file then refreshes the cache would make adding translations quite simple. It would however add an optional dependency for the philo/laravel-translate package.

If you agree, it might make sense to extract the actual array of translations to a separate file that is easier to generate. The config file could include this file.

What do you think? If you don't see this as part of your package I might set it up as it's own package.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.