├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── composer.json
└── src
├── Classes
└── ExportLocalizations.php
├── Console
└── Commands
│ ├── ExportMessages.php
│ └── ExportMessagesToFlat.php
├── Events
└── LaravelLocalizationExported.php
├── Facades
└── ExportLocalizations.php
├── LaravelLocalizationServiceProvider.php
├── config
└── laravel-localization.php
└── routes.php
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.phar
3 | composer.lock
4 | .DS_Store
5 | .idea
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at office@kg-studio.biz. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Stefan Ninic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://packagist.org/packages/kg-bot/laravel-localization-to-vue)
2 | [](https://packagist.org/packages/kg-bot/laravel-localization-to-vue)
3 | [](https://packagist.org/packages/kg-bot/laravel-localization-to-vue)
4 | [](https://packagist.org/packages/kg-bot/laravel-localization-to-vue)
5 | [](https://packagist.org/packages/kg-bot/laravel-localization-to-vue)
6 | [](https://packagist.org/packages/kg-bot/laravel-localization-to-vue)
7 |
8 |
9 |
10 |
11 | # Laravel Localization To Vue/JSON
12 |
13 | This package collects all localizations from resources/lang directory and it's sub-directories and converts them to plain array
14 | which can later be converted to JSON object and used with libraries like Vue, Angular, etc.
15 |
16 | ## Installing
17 |
18 | #### Laravel before version 9
19 |
20 | ```
21 | composer require kg-bot/laravel-localization-to-vue:^1
22 | ```
23 |
24 | #### Laravel 9
25 |
26 | ```
27 | composer require kg-bot/laravel-localization-to-vue:^2
28 | ```
29 |
30 |
31 | ### Laravel 8+
32 | Laravel 8 requires minimum of PHP 7.3. make sure you have at least PHP 7.3 before running composer.
33 |
34 | ### Laravel 9+
35 | Laravel 9 requires minimum of PHP 8.0.2 make sure you have at least PHP 8.0.2 before running composer.
36 |
37 | ### Laravel 5.5+
38 |
39 | Laravel 5.5 uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider.
40 |
41 | If you don't use auto-discovery, add the ServiceProvider to the providers array in config/app.php
42 | ```php
43 | KgBot\LaravelLocalization\LaravelLocalizationServiceProvider::class
44 | ```
45 |
46 | and if you want alias add this inside aliases array in config/app.php
47 | ```php
48 | "ExportLocalization" => "KgBot\\LaravelLocalization\\Facades\\ExportLocalizations"
49 | ```
50 |
51 | ## Settings and configuration
52 |
53 | You can export config by running
54 |
55 | ```php
56 | php artisan vendor:publish --provider="KgBot\LaravelLocalization\LaravelLocalizationServiceProvider" --tag=config
57 | ```
58 |
59 | if you want to parse multiple language directories or some other directory except `lang_path()` you can add multiple
60 | paths in config `paths.lang_dirs` inside array.
61 |
62 | It can be just one path or multiple paths, for example
63 | ```php
64 | paths => [lang_path(), app_path('lang'), app_path('Modules/Blog/lang')]
65 | ```
66 |
67 | You can run your own callback function after export, to do that you must register globally accessible function, for example
68 | register `function.php` inside composer files autoload, and add your function inside `config/laravel-localization.php`,
69 | key `export_callback`. Example:
70 | ```php
71 | // helpers/functions.php
72 |
73 | if (! function_exists('testExport')) {
74 | /**
75 | * Change all instances of :argument to {argument}
76 | *
77 | * @param $string
78 | * @return void
79 | *
80 | */
81 | function testExport($string) {
82 | array_walk_recursive($string, function (&$v, $k) { $v = preg_replace('/:(\w+)/', '{$1}', $v); });
83 |
84 | return $string;
85 | }
86 | }
87 |
88 |
89 | // composer.json
90 | ....
91 | "autoload": {
92 | "files": [
93 | "helpers/functions.php"
94 | ],
95 | "psr-4": {
96 | "App\\": "app/"
97 | },
98 | "classmap": [
99 | "database/seeds",
100 | "database/factories"
101 | ]
102 | },
103 | ....
104 |
105 | // config/laravel-localization.php
106 | ...
107 | 'export_callback' => 'testExport',
108 | ...
109 | ```
110 |
111 | # Usage
112 |
113 | This package can be used in multiple ways, I'll give examples for some of them, but there's really no limitation.
114 |
115 | First example would be to add view composed variable and use it in blade views.
116 |
117 | ```php
118 | // inside ServiceProvider
119 |
120 | // With alias
121 | use ExportLocalization;
122 |
123 | // Without alias
124 | use KgBot\LaravelLocalization\Facades\ExportLocalizations as ExportLocalization;
125 |
126 |
127 | View::composer( 'view.file', function ( $view ) {
128 |
129 | return $view->with( [
130 | 'messages' => ExportLocalization::export()->toArray(),
131 | ] );
132 | } );
133 | ```
134 |
135 | Second way would be to request it over HTTP just like any other file
136 |
137 | ```html
138 |
141 | ```
142 |
143 | For this to work, you need to enable the route via `LARAVEL_LOCALIZATION_ROUTE_ENABLE` in your `.env` file or in `config/laravel-localization.php`
144 |
145 | You can also export messages to ECMAScript 6 standard JavaScript module with artisan command
146 | ```` php artisan export:messages ````
147 |
148 | ## Export for npm localization packages like Lang.js
149 | If you need special format of array that's recognised by some npm localization packages as [Lang.js](https://github.com/rmariuzzo/Lang.js).
150 |
151 | ```php
152 | // Call toFlat() instead of toArray()
153 | ExportLocalization::export()->toFlat()
154 |
155 | or
156 |
157 | // For CLI usage
158 | php artisan export:messages-flat
159 |
160 | ```
161 |
162 | ## Some examples why would you use this package and messages over Laravel standard localization
163 |
164 | ```html
165 | // Inside blade view
166 |
171 | ```
172 |
173 | ```js
174 | // And optionaly you can then use it in any JavaScript file or Vue.js component
175 |
176 | // app.js
177 | import Vue from 'vue';
178 | import Lang from 'lang.js';
179 |
180 | const default_locale = window.default_language;
181 | const fallback_locale = window.fallback_locale;
182 | const messages = window.messages;
183 |
184 | Vue.prototype.trans = new Lang( { messages, locale: default_locale, fallback: fallback_locale } );
185 | ```
186 |
187 | ```html
188 | // Example.vue
189 |
193 | ```
194 |
195 | ## A note about json files
196 |
197 | Laravel 5.4+ allows localization to be strutured [using a single `.json` file for each language](https://laravel.com/docs/5.7/localization#using-translation-strings-as-keys), in order to use the strings inside the provided json file you must prepend the `__JSON__` key
198 |
199 | ```json
200 | // Assuming that es.json exists and it is the default locale in your app
201 | {
202 | "I love programming": "Me encanta programar"
203 | }
204 | ```
205 |
206 | ```html
207 | // Example.vue
208 |
209 | ```
210 |
211 | ## Routing
212 |
213 | This package exposes one route `http://localhost/js/localization.js` by default but you can change the prefix to anything you whish in config file.
214 |
215 | You can also have a nice route name for blade templates or any other route calls, it's `route('assets.lang')` by default but it's customizable by config/environment file.
216 |
217 | ## Proposals, comments, feedback
218 |
219 | Everything of this is highly welcome and appreciated
220 |
221 | ## To-Do
222 |
223 | + Create exclude configuration so not files/directories are collected
224 |
225 | Anything else you can think of please leave me comments, mail me, create issue, whatever you prefer.
226 |
227 | ## License
228 |
229 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
230 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kg-bot/laravel-localization-to-vue",
3 | "description": "Laravel package used to collect all localization files from resources/lang (and custom) directories and sub-directories and make them available as JSON file",
4 | "require": {
5 | "php": "^8.0",
6 | "laravel/framework": "5.*|^6|^7|^8|^9|^10.0|^11.0|^12.0",
7 | "ext-json": "*"
8 | },
9 | "keywords": [
10 | "laravel",
11 | "vue.js",
12 | "trans",
13 | "localization",
14 | "json"
15 | ],
16 | "license": "MIT",
17 | "authors": [
18 | {
19 | "name": "Stefan Ninic",
20 | "email": "ninicstefan94@gmail.com"
21 | }
22 | ],
23 | "autoload": {
24 | "psr-4": {
25 | "KgBot\\LaravelLocalization\\": "src/"
26 | }
27 | },
28 | "extra": {
29 | "laravel": {
30 | "providers": [
31 | "KgBot\\LaravelLocalization\\LaravelLocalizationServiceProvider"
32 | ],
33 | "aliases": {
34 | "ExportLocalization": "KgBot\\LaravelLocalization\\Facades\\ExportLocalizations"
35 | }
36 | }
37 | },
38 | "config": {
39 | "sort-packages": true
40 | },
41 | "minimum-stability": "dev",
42 | "prefer-stable": true,
43 | "funding": [
44 | {
45 | "type": "buy-me-a-coffee",
46 | "url": "https://rebrand.ly/laravel-localization-to-vue"
47 | }
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/src/Classes/ExportLocalizations.php:
--------------------------------------------------------------------------------
1 | phpRegex = $phpRegex;
50 | $this->jsonRegex = $jsonRegex;
51 | }
52 |
53 | /**
54 | * Method to return generate array with contents of parsed language files.
55 | *
56 | * @return object
57 | */
58 | public function export()
59 | {
60 | // Check if value is cached and set array to cached version
61 | if (Cache::has(config('laravel-localization.caches.key'))) {
62 | $this->strings = Cache::get(config('laravel-localization.caches.key'));
63 |
64 | return $this;
65 | }
66 |
67 | foreach (config('laravel-localization.paths.lang_dirs') as $dir) {
68 | try {
69 | // Collect language files and build array with translations
70 | $files = $this->findLanguageFiles($dir);
71 |
72 | // Parse translations and create final array
73 | array_walk($files['lang'], [$this, 'parseLangFiles'], $dir);
74 | array_walk($files['vendor'], [$this, 'parseVendorFiles'], $dir);
75 | array_walk($files['json'], [$this, 'parseJsonFiles'], $dir);
76 | } catch (\Exception $exception) {
77 | \Log::critical('Can\'t read lang directory '.$dir.', error: '.$exception->getMessage());
78 | }
79 | }
80 |
81 | // Trigger event for final translated array
82 | event(new LaravelLocalizationExported($this->strings));
83 |
84 | // If timeout > 0 save array to cache
85 | if (config('laravel-localization.caches.timeout', 0) > 0) {
86 | Cache::store(config('laravel-localization.caches.driver', 'file'))
87 | ->put(
88 | config('laravel-localization.caches.key', 'localization.array'),
89 | $this->strings,
90 | config('laravel-localization.caches.timeout', 60)
91 | );
92 | }
93 |
94 | return $this;
95 | }
96 |
97 | /**
98 | * Find available language files and parse them to array.
99 | *
100 | * @param string $path
101 | * @return array
102 | */
103 | protected function findLanguageFiles($path)
104 | {
105 | // Loop through directories
106 | $dirIterator = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
107 | $recIterator = new \RecursiveIteratorIterator($dirIterator);
108 |
109 | // Fetch only php files - skip others
110 | $phpFiles = array_values(
111 | array_map('current',
112 | iterator_to_array(
113 | new \RegexIterator($recIterator, $this->phpRegex, \RecursiveRegexIterator::GET_MATCH)
114 | )
115 | )
116 | );
117 |
118 | $jsonFiles = array_values(
119 | array_map('current',
120 | iterator_to_array(
121 | new \RegexIterator($recIterator, $this->jsonRegex, \RecursiveRegexIterator::GET_MATCH)
122 | )
123 | )
124 | );
125 |
126 | $files = array_merge($phpFiles, $jsonFiles);
127 |
128 | // Sort array by filepath
129 | sort($files);
130 |
131 | // Remove full path from items
132 | array_walk($files, function (&$item) use ($path) {
133 | $item = str_replace($path, '', $item);
134 | });
135 |
136 | // Fetch non-vendor files from filtered php files
137 | $nonVendorFiles = array_filter($files, function ($file) {
138 | return strpos($file, $this->excludePath) === false && strpos($file, '.json') === false;
139 | });
140 |
141 | // Fetch vendor files from filtered php files
142 | $vendorFiles = array_filter(array_diff($files, $nonVendorFiles), function ($file) {
143 | return strpos($file, 'json') === false;
144 | });
145 |
146 | // Fetch .json files from filtered files
147 | $jsonFiles = array_filter($files, function ($file) {
148 | return strpos($file, '.json') !== false;
149 | });
150 |
151 | return [
152 | 'lang' => array_values($nonVendorFiles),
153 | 'vendor' => array_values($vendorFiles),
154 | 'json' => array_values($jsonFiles),
155 | ];
156 | }
157 |
158 | /**
159 | * Method to return array for json serialization.
160 | *
161 | * @return array
162 | */
163 | public function jsonSerialize(): mixed
164 | {
165 | return self::executeCallback($this->strings);
166 | }
167 |
168 | /**
169 | * Method to return array.
170 | *
171 | * @return array
172 | */
173 | public function toArray()
174 | {
175 | return self::executeCallback($this->strings);
176 | }
177 |
178 | /**
179 | * If you need special format of array that's recognised by some npm localization packages as Lang.js
180 | * https://github.com/rmariuzzo/Lang.js use this method.
181 | *
182 | * @param array $array
183 | * @param string $prefix
184 | * @return array
185 | */
186 | public function toFlat($prefix = '.')
187 | {
188 | $results = [];
189 | $default_locale = config('laravel-localization.js.default_locale');
190 | $default_json_strings = null;
191 |
192 | foreach ($this->strings as $lang => $strings) {
193 | if ($lang !== 'json') {
194 | foreach ($strings as $lang_array => $lang_messages) {
195 | $key = $lang.$prefix.$lang_array;
196 | $results[$key] = $lang_messages;
197 | }
198 | } else {
199 | foreach ($strings as $json_lang => $json_strings) {
200 | $key = $json_lang.$prefix.'__JSON__';
201 | if (array_key_exists($key, $results)) {
202 | $results[$key] = $json_strings;
203 | } else {
204 | $results[$key] = $json_strings;
205 | }
206 |
207 | // Pick only the first $json_strings
208 | if (! $default_json_strings) {
209 | $default_json_strings = $json_strings;
210 | }
211 | }
212 | }
213 | }
214 |
215 | // Create a JSON key value pair for the default language
216 | $default_key = $default_locale.$prefix.'__JSON__';
217 | if (! array_key_exists($default_key, $results)) {
218 | $buffer = array_keys(
219 | $default_json_strings ? get_object_vars($default_json_strings) : []
220 | );
221 |
222 | $results[$default_key] = array_combine($buffer, $buffer);
223 | }
224 |
225 | return self::executeCallback($results);
226 | }
227 |
228 | /**
229 | * Method to return array as collection.
230 | *
231 | * @return \Illuminate\Support\Collection
232 | */
233 | public function toCollection()
234 | {
235 | return collect(self::executeCallback($this->strings));
236 | }
237 |
238 | /**
239 | * Method to parse language files.
240 | *
241 | * @param string $file
242 | */
243 | protected function parseLangFiles($file, $key, $dir)
244 | {
245 | // Base package name without file ending
246 | $packageName = basename($file, '.php');
247 |
248 | // Get package, language and file contents from language file
249 | // //(.php
250 | $language = explode(DIRECTORY_SEPARATOR, $file)[1];
251 | $fileContents = require $dir.DIRECTORY_SEPARATOR.$file;
252 |
253 | // Check if language already exists in array
254 | if (array_key_exists($language, $this->strings)) {
255 | if (array_key_exists($packageName, $this->strings[$language])) {
256 | $this->strings[$language][$packageName] =
257 | array_replace_recursive((array) $this->strings[$language][$packageName], (array)
258 | $fileContents);
259 | } else {
260 | $this->strings[$language][$packageName] = $fileContents;
261 | }
262 | } else {
263 | $this->strings[$language] = [
264 | $packageName => $fileContents,
265 | ];
266 | }
267 | }
268 |
269 | /**
270 | * Method to parse language files from vendor folder.
271 | *
272 | * @param string $file
273 | */
274 | protected function parseVendorFiles($file, $key, $dir)
275 | {
276 | // Base package name without file ending
277 | $packageName = basename($file, '.php');
278 |
279 | // Get package, language and file contents from language file
280 | // /vendor///.php
281 | $package = explode(DIRECTORY_SEPARATOR, $file)[2];
282 | $language = explode(DIRECTORY_SEPARATOR, $file)[3];
283 | $fileContents = require $dir.DIRECTORY_SEPARATOR.$file;
284 |
285 | // Check if language already exists in array
286 | if (array_key_exists($language, $this->strings)) {
287 | // Check if package already exists in language
288 | if (array_key_exists($package, $this->strings[$language])) {
289 | if (array_key_exists($packageName, $this->strings[$language][$package])) {
290 | $this->strings[$language][$package][$packageName] =
291 | array_replace_recursive((array) $this->strings[$language][$package][$packageName],
292 | (array)
293 | $fileContents);
294 | } else {
295 | $this->strings[$language][$package][$packageName] = $fileContents;
296 | }
297 | } else {
298 | $this->strings[$language][$package] = [$packageName => $fileContents];
299 | }
300 | } else {
301 | $this->strings[$language] = [
302 |
303 | $package => [
304 |
305 | $packageName => $fileContents,
306 | ],
307 | ];
308 | }
309 | }
310 |
311 | protected function parseJsonFiles($file, $key, $dir)
312 | {
313 | // Base package name without file ending
314 | $language = basename($file, '.json');
315 |
316 | // Get package, language and file contents from language file
317 | // //(.php
318 | $fileContents = json_decode(file_get_contents($dir.$file));
319 |
320 | // Check if language already exists in array
321 | if (array_key_exists('json', $this->strings)) {
322 | if (array_key_exists($language, $this->strings['json'])) {
323 | $this->strings['json'][$language] =
324 | array_replace_recursive((array) $this->strings['json'][$language], (array) $fileContents);
325 | } else {
326 | $this->strings['json'][$language] = $fileContents;
327 | }
328 | } else {
329 | $this->strings['json'] = [
330 |
331 | $language => $fileContents,
332 | ];
333 | }
334 | }
335 |
336 | public static function exportToArray()
337 | {
338 | return (new self(
339 | config('laravel-localization.file_regexp.php', '/^.+\.php$/i'),
340 | config('laravel-localization.file_regexp.json', '/^.+\.json$/i')
341 | ))->export()->toArray();
342 | }
343 |
344 | protected static function executeCallback($strings)
345 | {
346 | if ($callback = config('laravel-localization.export_callback')) {
347 | $strings = $callback($strings);
348 | }
349 |
350 | return $strings;
351 | }
352 | }
353 |
--------------------------------------------------------------------------------
/src/Console/Commands/ExportMessages.php:
--------------------------------------------------------------------------------
1 | filepath = config('laravel-localization.js.filepath', resource_path('assets/js'));
40 | $this->messages = ExportLocalizations::export()->toArray();
41 |
42 | $format = $this->argument('format');
43 |
44 | if ($format === 'javascript') {
45 | return $this->toJavaScript();
46 | }
47 | if ($format === 'json') {
48 | return $this->toJson();
49 | }
50 |
51 | $this->error("Format {$format} is not currently supported, you can use callback function if you need additional modification of exported array.");
52 |
53 | return 1;
54 | }
55 |
56 | protected function toJavaScript()
57 | {
58 | $filename = config('laravel-localization.js.filename', 'll_messages.js');
59 |
60 | $adapter = new Local($this->filepath);
61 | $filesystem = new Filesystem($adapter);
62 |
63 | $contents = 'export default '.json_encode($this->messages);
64 |
65 | if ($filesystem->has($filename)) {
66 | $filesystem->delete($filename);
67 | $filesystem->write($filename, $contents);
68 | } else {
69 | $filesystem->write($filename, $contents);
70 | }
71 |
72 | $this->info('Messages exported to JavaScript file, you can find them at '.$this->filepath.DIRECTORY_SEPARATOR
73 | .$filename);
74 |
75 | return 0;
76 | }
77 |
78 | protected function toJson()
79 | {
80 | foreach ($this->messages as $language_key => $translations) {
81 | foreach ($translations as $translation_key => $translate) {
82 | $filepath = "$this->filepath/$language_key";
83 | $filename = "$translation_key.json";
84 |
85 | $adapter = new Local($filepath);
86 | $filesystem = new Filesystem($adapter);
87 |
88 | $contents = json_encode($translate, JSON_PRETTY_PRINT);
89 |
90 | if ($filesystem->has($filename)) {
91 | $filesystem->delete($filename);
92 | $filesystem->write($filename, $contents);
93 | } else {
94 | $filesystem->write($filename, $contents);
95 | }
96 | }
97 | }
98 |
99 | $this->info('Messages exported to JSON files, you can find them at '.$this->filepath);
100 |
101 | return 0;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Console/Commands/ExportMessagesToFlat.php:
--------------------------------------------------------------------------------
1 | toFlat();
44 |
45 | $filepath = config('laravel-localization.js.filepath', resource_path('assets/js'));
46 | $filename = config('laravel-localization.js.filename', 'll_messages.js');
47 |
48 | $adapter = new Local($filepath);
49 | $filesystem = new Filesystem($adapter);
50 |
51 | $contents = 'export default '.json_encode($messages);
52 |
53 | if ($filesystem->has($filename)) {
54 | $filesystem->delete($filename);
55 | $filesystem->write($filename, $contents);
56 | } else {
57 | $filesystem->write($filename, $contents);
58 | }
59 |
60 | $this->info('Messages exported to JavaScript file, you can find them at '.$filepath.DIRECTORY_SEPARATOR
61 | .$filename);
62 |
63 | return 0;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Events/LaravelLocalizationExported.php:
--------------------------------------------------------------------------------
1 | messages = $messages;
25 | }
26 |
27 | /**
28 | * Get the channels the event should broadcast on.
29 | *
30 | * @return \Illuminate\Broadcasting\Channel|array
31 | */
32 | public function broadcastOn()
33 | {
34 | return new PrivateChannel(config('laravel-localization.events.channel', 'channel-name'));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Facades/ExportLocalizations.php:
--------------------------------------------------------------------------------
1 | app->bind(ExportLocalizations::class, function () {
21 | $phpRegex = config('laravel-localization.file_regexp.php', '/^.+\.php$/i');
22 | $jsonRegex = config('laravel-localization.file_regexp.json', '/^.+\.json$/i');
23 |
24 | return new ExportLocalizations($phpRegex, $jsonRegex);
25 | });
26 |
27 | $this->app->alias(ExportLocalizations::class, 'export-localization');
28 |
29 | /*
30 | * Config
31 | */
32 | $this->mergeConfigFrom(
33 | __DIR__.'/config/laravel-localization.php', 'laravel-localization'
34 | );
35 |
36 | $this->publishes([
37 | __DIR__.'/config/laravel-localization.php' => config_path('laravel-localization.php'),
38 | ], 'config');
39 |
40 | /*
41 | * Routes
42 | */
43 | $this->loadRoutesFrom(__DIR__.'/routes.php');
44 |
45 | if ($this->app->runningInConsole()) {
46 | $this->commands([
47 | ExportMessages::class,
48 | ExportMessagesToFlat::class,
49 | ]);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/config/laravel-localization.php:
--------------------------------------------------------------------------------
1 | [
12 |
13 | /**
14 | * Route prefix, example of route http://localhost/js/localizations.js.
15 | */
16 | 'prefix' => env('LARAVEL_LOCALIZATION_PREFIX', '/js/localization.js'),
17 |
18 | /**
19 | * Route name, defaults to assets.lang.
20 | */
21 | 'name' => env('LARAVEL_LOCALIZATION_ROUTE_NAME', 'assets.lang'),
22 |
23 | /**
24 | * Middleware used on localization routes.
25 | *
26 | * You can add more middleware with .env directive, example LARAVEL_LOCALIZATION_MIDDLEWARE=web,auth:api, etc.
27 | *
28 | * Don't use space in .env directive after ,
29 | */
30 | 'middleware' => (env('LARAVEL_LOCALIZATION_MIDDLEWARE')) ?
31 | explode(',', env('LARAVEL_LOCALIZATION_MIDDLEWARE'))
32 | : [],
33 |
34 | /**
35 | * Should we enable public URL from which we can access translations.
36 | */
37 | 'enable' => env('LARAVEL_LOCALIZATION_ROUTE_ENABLE', false),
38 | ],
39 | 'events' => [
40 |
41 | /**
42 | * This package emits some events after it getters all translation messages.
43 | *
44 | * Here you can change channel on which events will broadcast
45 | */
46 | 'channel' => env('LARAVEL_LOCALIZATION_EVENTS_CHANNEL', ''),
47 | ],
48 | 'caches' => [
49 |
50 | /**
51 | * What cache driver do you want to use - more information: https://laravel.com/docs/5.6/cache#driver-prerequisites.
52 | */
53 | 'driver' => 'file',
54 |
55 | /**
56 | * Key name of the cache entry for the localization array.
57 | */
58 | 'key' => 'localization.array',
59 |
60 | /**
61 | * Timeout of the cached data in minutes - set to 0 to disable.
62 | */
63 | 'timeout' => 60,
64 | ],
65 | 'js' => [
66 | /**
67 | * Default locale for export.
68 | */
69 | 'default_locale' => 'en',
70 |
71 | /**
72 | * root location to where JavaScript file will be exported.
73 | */
74 | 'filepath' => resource_path('assets/js'),
75 |
76 | /**
77 | * File name for JavaScript file with exported messages.
78 | */
79 | 'filename' => 'll_messages.js',
80 | ],
81 | 'paths' => [
82 |
83 | /**
84 | * You can export more lang files then just files in resources/lang, for example.
85 | *
86 | * In you .env file just add:
87 | * LARAVEL_LOCALIZATION_LANG_DIRS=resources/lang,Modules/Blog/Resources/lang
88 | */
89 | 'lang_dirs' => [lang_path()],
90 | ],
91 | /**
92 | * You can customize the regexp for lang files to be able to exclude certain files.
93 | */
94 | 'file_regexp' => [
95 | 'php' => '/^.+\.php$/i',
96 | 'json' => '/^.+\.json$/i',
97 | ],
98 | /**
99 | * This function will be called every time after export, it should be globally accessible function (eg. Laravel helper function)
100 | * and it should accept (string) argument.
101 | */
102 | 'export_callback' => null,
103 |
104 | ];
105 |
--------------------------------------------------------------------------------
/src/routes.php:
--------------------------------------------------------------------------------
1 | name(config('laravel-localization.routes.name'))
14 | ->middleware(config('laravel-localization.routes.middleware'));
15 | }
16 |
--------------------------------------------------------------------------------