├── .editorconfig
├── .github
├── CONTRIBUTING.md
├── FUNDING.yml
├── SECURITY.md
├── dependabot.yml
└── workflows
│ ├── dependabot-auto-merge.yml
│ ├── fix-php-code-style-issues.yml
│ ├── phpstan.yml
│ └── update-changelog.yml
├── .gitignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
├── composer.lock
├── docs
├── _index.md
├── filament.md
├── getting-started
│ ├── _index.md
│ ├── changelog.md
│ ├── installation.md
│ ├── upgrade.md
│ └── usage.md
└── introduction.md
├── phpstan.neon
├── pint.json
├── resources
└── lang
│ ├── ar
│ └── actions.php
│ ├── az
│ └── actions.php
│ ├── bn
│ └── actions.php
│ ├── ca
│ └── actions.php
│ ├── ckb
│ └── actions.php
│ ├── da
│ └── actions.php
│ ├── de
│ └── actions.php
│ ├── en
│ └── actions.php
│ ├── es
│ └── actions.php
│ ├── eu
│ └── actions.php
│ ├── fa
│ └── actions.php
│ ├── fi
│ └── actions.php
│ ├── fr
│ └── actions.php
│ ├── he
│ └── actions.php
│ ├── hr
│ └── actions.php
│ ├── hu
│ └── actions.php
│ ├── hy
│ └── actions.php
│ ├── id
│ └── actions.php
│ ├── it
│ └── actions.php
│ ├── ja
│ └── actions.php
│ ├── km
│ └── actions.php
│ ├── ku
│ └── actions.php
│ ├── lt
│ └── actions.php
│ ├── ms
│ └── actions.php
│ ├── my
│ └── actions.php
│ ├── nl
│ └── actions.php
│ ├── no
│ └── actions.php
│ ├── np
│ └── actions.php
│ ├── pt_BR
│ └── actions.php
│ ├── pt_PT
│ └── actions.php
│ ├── ro
│ └── actions.php
│ ├── ru
│ └── actions.php
│ ├── sk
│ └── actions.php
│ ├── sv
│ └── actions.php
│ ├── tr
│ └── actions.php
│ ├── uk
│ └── actions.php
│ ├── uz
│ └── actions.php
│ ├── vi
│ └── actions.php
│ ├── zh_CN
│ └── actions.php
│ └── zh_TW
│ └── actions.php
└── src
├── Actions
├── Concerns
│ └── HasTranslatableLocaleOptions.php
└── LocaleSwitcher.php
├── Pages
└── Actions
│ └── LocaleSwitcher.php
├── Resources
├── Concerns
│ ├── HasActiveLocaleSwitcher.php
│ └── Translatable.php
├── Pages
│ ├── Concerns
│ │ ├── HasTranslatableFormWithExistingRecordData.php
│ │ └── HasTranslatableRecord.php
│ ├── CreateRecord
│ │ └── Concerns
│ │ │ └── Translatable.php
│ ├── EditRecord
│ │ └── Concerns
│ │ │ └── Translatable.php
│ ├── ListRecords
│ │ └── Concerns
│ │ │ └── Translatable.php
│ ├── ManageRecords
│ │ └── Concerns
│ │ │ └── Translatable.php
│ └── ViewRecord
│ │ └── Concerns
│ │ └── Translatable.php
└── RelationManagers
│ └── Concerns
│ └── Translatable.php
├── SpatieLaravelTranslatableContentDriver.php
├── SpatieLaravelTranslatablePlugin.php
├── SpatieLaravelTranslatablePluginServiceProvider.php
└── Tables
└── Actions
└── LocaleSwitcher.php
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 4
7 | indent_style = space
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
14 | [*.{yml,yaml}]
15 | indent_size = 2
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are **welcome** and will be fully **credited**.
4 |
5 | Please read and understand the contribution guide before creating an issue or pull request.
6 |
7 | ## Etiquette
8 |
9 | This project is open source, and as such, the maintainers give their free time to build and maintain the source code
10 | held within. They make the code freely available in the hope that it will be of use to other developers. It would be
11 | extremely unfair for them to suffer abuse or anger for their hard work.
12 |
13 | Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the
14 | world that developers are civilized and selfless people.
15 |
16 | It's the duty of the maintainer to ensure that all submissions to the project are of sufficient
17 | quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.
18 |
19 | ## Viability
20 |
21 | When requesting or submitting new features, first consider whether it might be useful to others. Open
22 | source projects are used by many developers, who may have entirely different needs to your own. Think about
23 | whether or not your feature is likely to be used by other users of the project.
24 |
25 | ## Procedure
26 |
27 | Before filing an issue:
28 |
29 | - Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
30 | - Check to make sure your feature suggestion isn't already present within the project.
31 | - Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
32 | - Check the pull requests tab to ensure that the feature isn't already in progress.
33 |
34 | Before submitting a pull request:
35 |
36 | - Check the codebase to ensure that your feature doesn't already exist.
37 | - Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
38 |
39 | ## Requirements
40 |
41 | If the project maintainer has any additional requirements, you will find them listed here.
42 |
43 | - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer).
44 |
45 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests.
46 |
47 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
48 |
49 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
50 |
51 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
52 |
53 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
54 |
55 | **Happy coding**!
56 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [atmonshi, mohamedsabil83]
2 |
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | If you discover any security related issues, please email info@larazeus.com instead of using the issue tracker.
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Please see the documentation for all configuration options:
2 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
3 |
4 | version: 2
5 | updates:
6 |
7 | - package-ecosystem: "github-actions"
8 | directory: "/"
9 | schedule:
10 | interval: "weekly"
11 | labels:
12 | - "dependencies"
--------------------------------------------------------------------------------
/.github/workflows/dependabot-auto-merge.yml:
--------------------------------------------------------------------------------
1 | name: dependabot-auto-merge
2 | on: pull_request_target
3 |
4 | permissions:
5 | pull-requests: write
6 | contents: write
7 |
8 | jobs:
9 | dependabot:
10 | runs-on: ubuntu-latest
11 | if: ${{ github.actor == 'dependabot[bot]' }}
12 | steps:
13 |
14 | - name: Dependabot metadata
15 | id: metadata
16 | uses: dependabot/fetch-metadata@v2.1.0
17 | with:
18 | github-token: "${{ secrets.GITHUB_TOKEN }}"
19 |
20 | - name: Auto-merge Dependabot PRs for semver-minor updates
21 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}}
22 | run: gh pr merge --auto --merge "$PR_URL"
23 | env:
24 | PR_URL: ${{github.event.pull_request.html_url}}
25 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
26 |
27 | - name: Auto-merge Dependabot PRs for semver-patch updates
28 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
29 | run: gh pr merge --auto --merge "$PR_URL"
30 | env:
31 | PR_URL: ${{github.event.pull_request.html_url}}
32 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
--------------------------------------------------------------------------------
/.github/workflows/fix-php-code-style-issues.yml:
--------------------------------------------------------------------------------
1 | name: code style
2 |
3 | on: [push]
4 |
5 | jobs:
6 | php-code-styling:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - name: Checkout code
11 | uses: actions/checkout@v4
12 | with:
13 | ref: ${{ github.head_ref }}
14 |
15 | - name: Fix PHP code style issues
16 | uses: aglipanci/laravel-pint-action@2.4
17 |
18 | - name: Commit changes
19 | uses: stefanzweifel/git-auto-commit-action@v5
20 | with:
21 | commit_message: Fix styling
22 |
--------------------------------------------------------------------------------
/.github/workflows/phpstan.yml:
--------------------------------------------------------------------------------
1 | name: PHPStan
2 |
3 | on:
4 | push:
5 | paths:
6 | - '**.php'
7 | - 'phpstan.neon.dist'
8 |
9 | jobs:
10 | phpstan:
11 | name: phpstan
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v4
15 |
16 | - name: Setup PHP
17 | uses: shivammathur/setup-php@v2
18 | with:
19 | php-version: '8.2'
20 | coverage: none
21 |
22 | - name: Install composer dependencies
23 | uses: ramsey/composer-install@v3
24 |
25 | - name: Run PHPStan
26 | run: ./vendor/bin/phpstan --error-format=github
--------------------------------------------------------------------------------
/.github/workflows/update-changelog.yml:
--------------------------------------------------------------------------------
1 | name: "Update Changelog"
2 |
3 | on:
4 | release:
5 | types: [released]
6 |
7 | jobs:
8 | update:
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v4
14 | with:
15 | ref: 3.x
16 |
17 | - name: Update Changelog
18 | uses: stefanzweifel/changelog-updater-action@v1
19 | with:
20 | latest-version: ${{ github.event.release.name }}
21 | release-notes: ${{ github.event.release.body }}
22 |
23 | - name: Commit updated CHANGELOG
24 | uses: stefanzweifel/git-auto-commit-action@v5
25 | with:
26 | branch: 3.x
27 | commit_message: Update CHANGELOG
28 | file_pattern: CHANGELOG.md
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /public/hot
3 | /public/storage
4 | /storage/*.key
5 | /vendor
6 | /vendor/.idea
7 | /bootstrap/cache
8 | .env
9 | .env.backup
10 | .phpunit.result.cache
11 | docker-compose.override.yml
12 | Homestead.json
13 | Homestead.yaml
14 | npm-debug.log
15 | yarn-error.log
16 | /.idea
17 | /.vscode
18 | /pkg
19 | /build
20 | .DS_Store
21 | /.phpunit.cache
22 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lara-zeus/translatable/610a3f1f2153f98e258c3e943e1d5658ae5354e6/CHANGELOG.md
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) php coder
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lara Zeus Translatable is Filament support for Spatie's Laravel Translatable package.
6 |
7 | ## Support Filament
8 |
9 |
10 |
11 |
12 |
13 | ## Introduction
14 |
15 | This repository is a fork of the [Filament Spatie Laravel Translatable plugin](https://github.com/filamentphp/spatie-laravel-translatable-plugin), maintained by [Mohamed Sabil](https://github.com/mohamedsabil83) and [Lara Zeus](https://github.com/lara-zeus).
16 |
17 | Our objective is to address existing issues, introduce additional features, and enhance the overall functionality of the plugin.
18 |
19 | We are committed to providing ongoing improvements and welcome contributions and suggestions from the community.
20 |
21 | ## Features
22 |
23 | - 🔥 Using Spatie translatable package
24 | - 🔥 default translatable locales
25 | - 🔥 Locale Switcher
26 | - 🔥 Support for create, edit, list and view pages
27 | - 🔥 Setting the translatable locales for a particular resource
28 | - 🔥 Translating relation managers
29 |
30 | ## Full Documentation
31 |
32 | > Visit our website to get the complete documentation: https://larazeus.com/docs/translatable
33 |
34 | ### Important Note on Using the Local Switcher
35 |
36 | Please be aware that there are some known limitations when using the local switcher with certain complex field types.
37 |
38 | To avoid potential issues, we recommend disabling the local switcher and using the specified field types instead.
39 |
40 | #### Available Components for Translatable Fields:
41 |
42 | * https://filamentphp.com/plugins/abdulmajeed-jamaan-translatable-tabs
43 | * https://filamentphp.com/plugins/solution-forest-translate-field
44 | * https://filamentphp.com/plugins/mvenghaus-translatable-inline
45 | * https://filamentphp.com/plugins/outerweb-translatable-fields
46 | * https://filamentphp.com/plugins/34ml-translatable-field
47 |
48 | You can also create your own custom fields. Please refer to the following example:
49 |
50 | * https://github.com/lara-zeus/chaos/blob/1.x/src/Forms/Components/MultiLang.php
51 |
52 | ## Changelog
53 |
54 | Please see [CHANGELOG](CHANGELOG.md) for more information on recent changes.
55 |
56 | ## Support
57 | available support channels:
58 | * open an issue on [GitHub](https://github.com/lara-zeus/translatable/issues)
59 | * Email us using the [contact center](https://larazeus.com/contact-us)
60 |
61 | ## Contributing
62 |
63 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
64 |
65 | ## Security
66 |
67 | If you find any security-related issues, please email info@larazeus.com instead of using the issue tracker.
68 |
69 | ## Credits
70 |
71 | - [Dan Harrin](https://github.com/danharrin)
72 | - [php coder](https://github.com/atmonshi)
73 | - [Mohamed Sabil](https://github.com/mohamedsabil83)
74 | - [All Contributors](../../contributors)
75 |
76 | ## License
77 |
78 | The MIT License (MIT). Please have a look at [License File](LICENSE.md) for more information.
79 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "filament/spatie-laravel-translatable-plugin",
3 | "description": "Filament support for `spatie/laravel-translatable`.",
4 | "license": "MIT",
5 | "homepage": "https://github.com/filamentphp/filament",
6 | "support": {
7 | "issues": "https://github.com/filamentphp/filament/issues",
8 | "source": "https://github.com/filamentphp/filament"
9 | },
10 | "require": {
11 | "php": "^8.1",
12 | "filament/filament": "^3.0",
13 | "spatie/laravel-translatable": "^6.0"
14 | },
15 | "require-dev": {
16 | "larastan/larastan": "^2.0",
17 | "laravel/pint": "^1.0",
18 | "orchestra/testbench": "^8.0",
19 | "phpstan/extension-installer": "^1.1"
20 | },
21 | "autoload": {
22 | "psr-4": {
23 | "Filament\\": "src"
24 | }
25 | },
26 | "extra": {
27 | "laravel": {
28 | "providers": [
29 | "Filament\\SpatieLaravelTranslatablePluginServiceProvider"
30 | ]
31 | }
32 | },
33 | "config": {
34 | "sort-packages": true,
35 | "allow-plugins": {
36 | "phpstan/extension-installer": true
37 | }
38 | },
39 | "minimum-stability": "dev",
40 | "prefer-stable": true
41 | }
42 |
--------------------------------------------------------------------------------
/docs/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: v3
3 | slogan: Filament support for Spatie's Laravel Translatable package.
4 | githubUrl: https://github.com/lara-zeus/translatable
5 | branch: 3.x
6 | icon: carbon-translate
7 | ---
8 |
--------------------------------------------------------------------------------
/docs/filament.md:
--------------------------------------------------------------------------------
1 | # Filament Translatable
2 |
3 | Translatable is Filament support for Spatie's Laravel Translatable package.
4 |
5 | ## Features
6 |
7 | - 🔥 Using Spatie translatable package
8 | - 🔥 Default translatable locales
9 | - 🔥 Locale Switcher
10 | - 🔥 Support for create, edit, list and view pages
11 | - 🔥 Setting the translatable locales for a particular resource
12 | - 🔥 Translating relation managers
13 |
14 | ## More Details
15 |
16 | **✨ to learn more about Translatable, please visit:**
17 |
18 | - [Docs](https://larazeus.com/docs/translatable)
19 |
20 | ## Important Note on Using the Local Switcher
21 |
22 | Please be aware that there are some known limitations when using the local switcher with certain complex field types.
23 |
24 | To avoid potential issues, we recommend disabling the local switcher and using the specified field types instead.
25 |
26 | ### Available Components for Translatable Fields:
27 |
28 | * https://filamentphp.com/plugins/solution-forest-translate-field
29 | * https://filamentphp.com/plugins/mvenghaus-translatable-inline
30 | * https://filamentphp.com/plugins/outerweb-translatable-fields
31 | * https://filamentphp.com/plugins/34ml-translatable-field
32 |
33 | You can also create your own custom fields. Please refer to the following example:
34 |
35 | * https://github.com/lara-zeus/chaos/blob/1.x/src/Forms/Components/MultiLang.php
36 |
37 |
--------------------------------------------------------------------------------
/docs/getting-started/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started
3 | weight: 1
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/getting-started/changelog.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Changelog
3 | weight: 100
4 | ---
5 |
6 | All changes to @zeus Translatable are auto updated documented on our site [changelog](https://larazeus.com/translatable)
7 |
--------------------------------------------------------------------------------
/docs/getting-started/installation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Installation
3 | weight: 2
4 | ---
5 |
6 | ## Installation
7 |
8 | First add this repo URL to your composer:
9 |
10 | ```json
11 | "repositories": [
12 | {
13 | "type": "github",
14 | "url": "https://github.com/lara-zeus/translatable"
15 | },
16 | ]
17 | ```
18 |
19 | and make sure your minimum stability is set to dev:
20 |
21 | ```json
22 | "minimum-stability": "dev",
23 | ```
24 |
25 | Then Install the plugin with Composer:
26 |
27 | ```bash
28 | composer require filament/spatie-laravel-translatable-plugin:"^3.2" -W
29 | ```
30 |
31 | ## Adding the plugin to a panel
32 |
33 | To add a plugin to a panel, you must include it in the configuration file using the `plugin()` method:
34 |
35 | ```php
36 | use Filament\SpatieLaravelTranslatablePlugin;
37 |
38 | public function panel(Panel $panel): Panel
39 | {
40 | return $panel
41 | // ...
42 | ->plugin(SpatieLaravelTranslatablePlugin::make());
43 | }
44 | ```
45 |
46 | ## Setting the default translatable locales
47 |
48 | To set up the locales that can be used to translate content, you can pass an array of locales to the `defaultLocales()` plugin method:
49 |
50 | ```php
51 | use Filament\SpatieLaravelTranslatablePlugin;
52 |
53 | public function panel(Panel $panel): Panel
54 | {
55 | return $panel
56 | // ...
57 | ->plugin(
58 | SpatieLaravelTranslatablePlugin::make()
59 | ->defaultLocales(['en', 'es']),
60 | );
61 | }
62 | ```
63 |
64 | ## Preparing your model class
65 |
66 | You need to make your model translatable. You can read how to do this in [Spatie's documentation](https://spatie.be/docs/laravel-translatable/installation-setup#content-making-a-model-translatable).
67 |
68 | ## Preparing your resource class
69 |
70 | You must apply the `Filament\Resources\Concerns\Translatable` trait to your resource class:
71 |
72 | ```php
73 | use Filament\Resources\Concerns\Translatable;
74 | use Filament\Resources\Resource;
75 |
76 | class BlogPostResource extends Resource
77 | {
78 | use Translatable;
79 |
80 | // ...
81 | }
82 | ```
--------------------------------------------------------------------------------
/docs/getting-started/upgrade.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Upgrading
3 | weight: 90
4 | ---
5 |
6 | ## upgrade to v1
7 |
8 | soon
--------------------------------------------------------------------------------
/docs/getting-started/usage.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Usage
3 | weight: 4
4 | ---
5 |
6 | ## Making resource pages translatable
7 |
8 | After [preparing your resource class](#preparing-your-resource-class), you must make each of your resource's pages translatable too. You can find your resource's pages in the `Pages` directory of each resource folder. To prepare a page, you must apply the corresponding `Translatable` trait to it, and install a `LocaleSwitcher` header action:
9 |
10 | ```php
11 | use Filament\Actions;
12 | use Filament\Resources\Pages\ListRecords;
13 |
14 | class ListBlogPosts extends ListRecords
15 | {
16 | use ListRecords\Concerns\Translatable;
17 |
18 | protected function getHeaderActions(): array
19 | {
20 | return [
21 | Actions\LocaleSwitcher::make(),
22 | // ...
23 | ];
24 | }
25 |
26 | // ...
27 | }
28 | ```
29 |
30 | ```php
31 | use Filament\Actions;
32 | use Filament\Resources\Pages\CreateRecord;
33 |
34 | class CreateBlogPost extends CreateRecord
35 | {
36 | use CreateRecord\Concerns\Translatable;
37 |
38 | protected function getHeaderActions(): array
39 | {
40 | return [
41 | Actions\LocaleSwitcher::make(),
42 | // ...
43 | ];
44 | }
45 |
46 | // ...
47 | }
48 | ```
49 |
50 | ```php
51 | use Filament\Actions;
52 | use Filament\Resources\Pages\EditRecord;
53 |
54 | class EditBlogPost extends EditRecord
55 | {
56 | use EditRecord\Concerns\Translatable;
57 |
58 | protected function getHeaderActions(): array
59 | {
60 | return [
61 | Actions\LocaleSwitcher::make(),
62 | // ...
63 | ];
64 | }
65 |
66 | // ...
67 | }
68 | ```
69 |
70 | And if you have a `ViewRecord` page for your resource:
71 |
72 | ```php
73 | use Filament\Actions;
74 | use Filament\Resources\Pages\ViewRecord;
75 |
76 | class ViewBlogPost extends ViewRecord
77 | {
78 | use ViewRecord\Concerns\Translatable;
79 |
80 | protected function getHeaderActions(): array
81 | {
82 | return [
83 | Actions\LocaleSwitcher::make(),
84 | // ...
85 | ];
86 | }
87 |
88 | // ...
89 | }
90 | ```
91 |
92 | If you're using a simple resource, you can make the `ManageRecords` page translatable instead:
93 |
94 | ```php
95 | use Filament\Actions;
96 | use Filament\Resources\Pages\ManageRecords;
97 |
98 | class ManageBlogPosts extends ListRecords
99 | {
100 | use ManageRecords\Concerns\Translatable;
101 |
102 | protected function getHeaderActions(): array
103 | {
104 | return [
105 | Actions\LocaleSwitcher::make(),
106 | // ...
107 | ];
108 | }
109 |
110 | // ...
111 | }
112 | ```
113 |
114 | ### Setting the translatable locales for a particular resource
115 |
116 | By default, the translatable locales can be [set globally for all resources in the plugin configuration](#setting-the-default-translatable-locales). Alternatively, you can customize the translatable locales for a particular resource by overriding the `getTranslatableLocales()` method in your resource class:
117 |
118 | ```php
119 | use Filament\Resources\Concerns\Translatable;
120 | use Filament\Resources\Resource;
121 |
122 | class BlogPostResource extends Resource
123 | {
124 | use Translatable;
125 |
126 | // ...
127 |
128 | public static function getTranslatableLocales(): array
129 | {
130 | return ['en', 'fr'];
131 | }
132 | }
133 | ```
134 |
135 | ## Translating relation managers
136 |
137 | First, you must apply the `Filament\Resources\RelationManagers\Concerns\Translatable` trait to the relation manager class:
138 |
139 | ```php
140 | use Filament\Resources\RelationManagers\Concerns\Translatable;
141 | use Filament\Resources\RelationManagers\RelationManager;
142 |
143 | class BlogPostsRelationManager extends RelationManager
144 | {
145 | use Translatable;
146 |
147 | // ...
148 | }
149 | ```
150 |
151 | Now, you can add a new `LocaleSwitcher` action to the header of the relation manager's `table()`:
152 |
153 | ```php
154 | use Filament\Tables;
155 | use Filament\Tables\Table;
156 |
157 | public function table(Table $table): Table
158 | {
159 | return $table
160 | ->columns([
161 | // ...
162 | ])
163 | ->headerActions([
164 | // ...
165 | Tables\Actions\LocaleSwitcher::make(),
166 | ]);
167 | }
168 | ```
169 |
170 | ### Inheriting the relation manager's active locale from the resource page
171 |
172 | If you wish to reactively inherit the locale of the `Translatable` resource page that the relation manager is being displayed on, you can override the `$activeLocale` property and add Livewire's `Reactive` attribute to it:
173 |
174 | ```php
175 | use Filament\Resources\RelationManagers\Concerns\Translatable;
176 | use Filament\Resources\RelationManagers\RelationManager;
177 | use Livewire\Attributes\Reactive;
178 |
179 | class BlogPostsRelationManager extends RelationManager
180 | {
181 | use Translatable;
182 |
183 | #[Reactive]
184 | public ?string $activeLocale = null;
185 |
186 | // ...
187 | }
188 | ```
189 |
190 | If you do this, you no longer need a `LocaleSwitcher` action in the `table()`.
191 |
192 | ### Setting the translatable locales for a particular relation manager
193 |
194 | By default, the translatable locales can be [set globally for all relation managers in the plugin configuration](#setting-the-default-translatable-locales). Alternatively, you can customize the translatable locales for a particular relation manager by overriding the `getTranslatableLocales()` method in your relation manager class:
195 |
196 | ```php
197 | use Filament\Resources\RelationManagers\Concerns\Translatable;
198 | use Filament\Resources\RelationManagers\RelationManager;
199 |
200 | class BlogPostsRelationManager extends RelationManager
201 | {
202 | use Translatable;
203 |
204 | // ...
205 |
206 | public function getTranslatableLocales(): array
207 | {
208 | return ['en', 'fr'];
209 | }
210 | }
211 | ```
212 |
213 | ## Publishing translations
214 |
215 | If you wish to translate the package, you may publish the language files using:
216 |
217 | ```bash
218 | php artisan vendor:publish --tag=filament-spatie-laravel-translatable-plugin-translations
219 | ```
220 |
--------------------------------------------------------------------------------
/docs/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | weight: 1
4 | ---
5 |
6 | ## Introduction
7 | @zeus Translatable is Filament support for Spatie's Laravel Translatable package.
8 |
9 | ## Features
10 |
11 | - 🔥 Using Spatie translatable package
12 | - 🔥 default translatable locales
13 | - 🔥 Locale Switcher
14 | - 🔥 Support for create, edit, list and view pages
15 | - 🔥 Setting the translatable locales for a particular resource
16 | - 🔥 Translating relation managers
17 |
18 | ## More Details
19 |
20 | **✨ to learn more about Translatable, please visit:**
21 |
22 | - [Docs](https://larazeus.com/docs/translatable)
23 |
24 | ## Important Note on Using the Local Switcher
25 |
26 | Please be aware that there are some known limitations when using the local switcher with certain complex field types.
27 |
28 | To avoid potential issues, we recommend disabling the local switcher and using the specified field types instead.
29 |
30 | ### Available Components for Translatable Fields:
31 |
32 | * https://filamentphp.com/plugins/solution-forest-translate-field
33 | * https://filamentphp.com/plugins/mvenghaus-translatable-inline
34 | * https://filamentphp.com/plugins/outerweb-translatable-fields
35 | * https://filamentphp.com/plugins/34ml-translatable-field
36 |
37 | You can also create your own custom fields. Please refer to the following example:
38 |
39 | * https://github.com/lara-zeus/chaos/blob/1.x/src/Forms/Components/MultiLang.php
40 |
41 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | level: 9
3 | paths:
4 | - src
5 |
6 | checkOctaneCompatibility: true
7 | checkModelProperties: true
8 |
9 | ignoreErrors:
10 | -
11 | identifier: missingType.iterableValue
12 | -
13 | identifier: missingType.generics
14 |
--------------------------------------------------------------------------------
/pint.json:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "laravel",
3 | "rules": {
4 | "blank_line_before_statement": true,
5 | "concat_space": {
6 | "spacing": "one"
7 | },
8 | "method_argument_space": true,
9 | "single_trait_insert_per_statement": true,
10 | "types_spaces": {
11 | "space": "single"
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/resources/lang/ar/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'اللغة',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/az/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Aktiv dil',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/bn/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'ভাষা',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/ca/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Idioma',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/ckb/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'ناوچە/زمان',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/da/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Sprog',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/de/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Sprache',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/en/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Locale',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/es/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Idioma',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/eu/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Hizkuntza',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/fa/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'زبان',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/fi/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Lokaali',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/fr/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Locale',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/he/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'שפה',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/hr/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Lokalitet',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/hu/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Nyelv',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/hy/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Տեղայնություն',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/id/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Bahasa',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/it/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Locale',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/ja/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'ロケール',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/km/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'ទីតាំង',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/ku/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'ناوچە/زمان',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/lt/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Kalba',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/ms/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Locale',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/my/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'ဘာသာစကား',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/nl/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Taal',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/no/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Språk',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/np/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'स्थानीय भाषा',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/pt_BR/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Idioma',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/pt_PT/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Idioma',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/ro/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Limba',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/ru/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Язык',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/sk/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Jazyk',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/sv/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Språk',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/tr/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Aktif Dil',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/uk/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Мова',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/uz/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Mahalliy',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/vi/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => 'Ngôn ngữ',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/zh_CN/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => '语言环境',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/resources/lang/zh_TW/actions.php:
--------------------------------------------------------------------------------
1 | [
6 | 'label' => '語系',
7 | ],
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/src/Actions/Concerns/HasTranslatableLocaleOptions.php:
--------------------------------------------------------------------------------
1 | options(function (): array {
12 | $livewire = $this->getLivewire();
13 |
14 | if (! method_exists($livewire, 'getTranslatableLocales')) {
15 | return [];
16 | }
17 |
18 | $locales = [];
19 |
20 | /** @var SpatieLaravelTranslatablePlugin $plugin */
21 | $plugin = filament('spatie-laravel-translatable');
22 |
23 | foreach ($livewire->getTranslatableLocales() as $locale) {
24 | $locales[$locale] = $plugin->getLocaleLabel($locale) ?? $locale;
25 | }
26 |
27 | return $locales;
28 | });
29 |
30 | return $this;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Actions/LocaleSwitcher.php:
--------------------------------------------------------------------------------
1 | label(__('filament-spatie-laravel-translatable-plugin::actions.active_locale.label'));
19 |
20 | $this->setTranslatableLocaleOptions();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Pages/Actions/LocaleSwitcher.php:
--------------------------------------------------------------------------------
1 | activeLocale, $this->getTranslatableLocales())) {
15 | return null;
16 | }
17 |
18 | return $this->activeLocale;
19 | }
20 |
21 | public function getActiveActionsLocale(): ?string
22 | {
23 | return $this->activeLocale;
24 | }
25 |
26 | /**
27 | * @return class-string | null
28 | */
29 | public function getFilamentTranslatableContentDriver(): ?string
30 | {
31 | return SpatieLaravelTranslatableContentDriver::class;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Resources/Concerns/Translatable.php:
--------------------------------------------------------------------------------
1 | getTranslatableAttributes();
24 |
25 | if (! count($attributes)) {
26 | throw new Exception("Model [{$model}] must have [\$translatable] properties defined.");
27 | }
28 |
29 | return $attributes;
30 | }
31 |
32 | public static function getTranslatableLocales(): array
33 | {
34 | return filament('spatie-laravel-translatable')->getDefaultLocales();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php:
--------------------------------------------------------------------------------
1 | activeLocale ??= $this->getDefaultTranslatableLocale();
15 |
16 | $record = $this->getRecord();
17 | $translatableAttributes = static::getResource()::getTranslatableAttributes();
18 |
19 | foreach ($this->getTranslatableLocales() as $locale) {
20 | $translatedData = [];
21 |
22 | foreach ($translatableAttributes as $attribute) {
23 | $translatedData[$attribute] = $record->getTranslation(
24 | $attribute,
25 | $locale,
26 | useFallbackLocale: filament('spatie-laravel-translatable')->getUseFallbackLocale()
27 | );
28 | }
29 |
30 | if ($locale !== $this->activeLocale) {
31 | $this->otherLocaleData[$locale] = $this->mutateFormDataBeforeFill($translatedData);
32 |
33 | continue;
34 | }
35 |
36 | /** @internal Read the DocBlock above the following method. */
37 | $this->fillFormWithDataAndCallHooks($record, $translatedData);
38 | }
39 | }
40 |
41 | protected function getDefaultTranslatableLocale(): string
42 | {
43 | $resource = static::getResource();
44 |
45 | $availableLocales = array_keys($this->getRecord()->getTranslations($resource::getTranslatableAttributes()[0]));
46 | $defaultLocale = $resource::getDefaultTranslatableLocale();
47 |
48 | if (in_array($defaultLocale, $availableLocales)) {
49 | return $defaultLocale;
50 | }
51 |
52 | $resourceLocales = $this->getTranslatableLocales();
53 |
54 | return array_intersect($availableLocales, $resourceLocales)[0] ?? $defaultLocale;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Resources/Pages/Concerns/HasTranslatableRecord.php:
--------------------------------------------------------------------------------
1 | activeLocale)) {
12 | return $this->record;
13 | }
14 |
15 | return $this->record->setLocale($this->activeLocale);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Resources/Pages/CreateRecord/Concerns/Translatable.php:
--------------------------------------------------------------------------------
1 | activeLocale = static::getResource()::getDefaultTranslatableLocale();
24 | }
25 |
26 | public function getTranslatableLocales(): array
27 | {
28 | return static::getResource()::getTranslatableLocales();
29 | }
30 |
31 | protected function handleRecordCreation(array $data): Model
32 | {
33 | $record = app(static::getModel());
34 |
35 | $translatableAttributes = static::getResource()::getTranslatableAttributes();
36 |
37 | $record->fill(
38 | Arr::except($data, $translatableAttributes)
39 | );
40 |
41 | foreach (Arr::only($data, $translatableAttributes) as $key => $value) {
42 | $record->setTranslation($key, $this->activeLocale, $value);
43 | }
44 |
45 | foreach ($this->otherLocaleData as $locale => $localeData) {
46 | try {
47 | $this->form->fill($this->form->getRawState());
48 | $this->form->validate();
49 | } catch (ValidationException $exception) {
50 | continue;
51 | }
52 |
53 | $localeData = $this->mutateFormDataBeforeCreate($localeData);
54 |
55 | foreach (Arr::only($localeData, $translatableAttributes) as $key => $value) {
56 | $record->setTranslation($key, $locale, $value);
57 | }
58 | }
59 |
60 | if (
61 | static::getResource()::isScopedToTenant() &&
62 | ($tenant = Filament::getTenant())
63 | ) {
64 | return $this->associateRecordWithTenant($record, $tenant);
65 | }
66 |
67 | $record->save();
68 |
69 | return $record;
70 | }
71 |
72 | public function updatingActiveLocale(): void
73 | {
74 | $this->oldActiveLocale = $this->activeLocale;
75 | }
76 |
77 | public function updatedActiveLocale(string $newActiveLocale): void
78 | {
79 | if (blank($this->oldActiveLocale)) {
80 | return;
81 | }
82 |
83 | $this->resetValidation();
84 |
85 | $translatableAttributes = static::getResource()::getTranslatableAttributes();
86 |
87 | try {
88 | $this->otherLocaleData[$this->oldActiveLocale] = Arr::only(
89 | $this->form->getRawState(),
90 | $translatableAttributes
91 | );
92 |
93 | $this->form->fill([
94 | ...Arr::except(
95 | $this->form->getRawState(),
96 | $translatableAttributes
97 | ),
98 | ...$this->otherLocaleData[$this->activeLocale] ?? [],
99 | ]);
100 |
101 | unset($this->otherLocaleData[$this->activeLocale]);
102 | } catch (ValidationException $e) {
103 | $this->activeLocale = $this->oldActiveLocale;
104 |
105 | throw $e;
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/Resources/Pages/EditRecord/Concerns/Translatable.php:
--------------------------------------------------------------------------------
1 | fill(
30 | Arr::except($data, $translatableAttributes)
31 | );
32 |
33 | foreach (Arr::only($data, $translatableAttributes) as $key => $value) {
34 | $record->setTranslation($key, $this->activeLocale, $value);
35 | }
36 |
37 | foreach ($this->otherLocaleData as $locale => $localeData) {
38 | $existingLocales ??= collect($translatableAttributes)
39 | ->map(fn (string $attribute): array => array_keys($record->getTranslations($attribute)))
40 | ->flatten()
41 | ->unique()
42 | ->all();
43 |
44 | try {
45 | $this->form->fill($this->form->getState(false));
46 | $this->form->validate();
47 | } catch (ValidationException $exception) {
48 | if (! array_key_exists($locale, $existingLocales)) {
49 | continue;
50 | }
51 |
52 | $this->setActiveLocale($locale);
53 |
54 | throw $exception;
55 | }
56 |
57 | $localeData = $this->mutateFormDataBeforeSave($localeData);
58 |
59 | foreach (Arr::only($localeData, $translatableAttributes) as $key => $value) {
60 | $record->setTranslation($key, $locale, $value);
61 | }
62 | }
63 |
64 | $record->save();
65 |
66 | return $record;
67 | }
68 |
69 | public function updatingActiveLocale(): void
70 | {
71 | $this->oldActiveLocale = $this->activeLocale;
72 | }
73 |
74 | public function updatedActiveLocale(): void
75 | {
76 | if (blank($this->oldActiveLocale)) {
77 | return;
78 | }
79 |
80 | $this->resetValidation();
81 | $translatableAttributes = static::getResource()::getTranslatableAttributes();
82 |
83 | try {
84 | $this->otherLocaleData[$this->oldActiveLocale] = Arr::only(
85 | $this->form->getRawState(),
86 | $translatableAttributes
87 | );
88 |
89 | $this->form->fill([
90 | ...Arr::except(
91 | $this->form->getRawState(),
92 | $translatableAttributes
93 | ),
94 | ...$this->otherLocaleData[$this->activeLocale] ?? [],
95 | ]);
96 |
97 | unset($this->otherLocaleData[$this->activeLocale]);
98 | } catch (ValidationException $e) {
99 | $this->activeLocale = $this->oldActiveLocale;
100 |
101 | throw $e;
102 | }
103 | }
104 |
105 | public function setActiveLocale(string $locale): void
106 | {
107 | $this->updatingActiveLocale();
108 | $this->activeLocale = $locale;
109 | $this->updatedActiveLocale();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/Resources/Pages/ListRecords/Concerns/Translatable.php:
--------------------------------------------------------------------------------
1 | activeLocale = static::getResource()::getDefaultTranslatableLocale();
14 | }
15 |
16 | public function getTranslatableLocales(): array
17 | {
18 | return static::getResource()::getTranslatableLocales();
19 | }
20 |
21 | public function getActiveTableLocale(): ?string
22 | {
23 | return $this->activeLocale;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Resources/Pages/ManageRecords/Concerns/Translatable.php:
--------------------------------------------------------------------------------
1 | oldActiveLocale = $this->activeLocale;
21 | }
22 |
23 | public function updatedActiveLocale(string $newActiveLocale): void
24 | {
25 | if (blank($this->oldActiveLocale)) {
26 | return;
27 | }
28 |
29 | $translatableAttributes = static::getResource()::getTranslatableAttributes();
30 |
31 | $this->otherLocaleData[$this->oldActiveLocale] = Arr::only($this->data, $translatableAttributes);
32 | $this->data = [
33 | ...$this->data,
34 | ...$this->otherLocaleData[$this->activeLocale] ?? [],
35 | ];
36 | }
37 |
38 | public function getTranslatableLocales(): array
39 | {
40 | return static::getResource()::getTranslatableLocales();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Resources/RelationManagers/Concerns/Translatable.php:
--------------------------------------------------------------------------------
1 | activeLocale) ||
15 | (! in_array($this->activeLocale, $this->getTranslatableLocales()))
16 | ) {
17 | $this->setActiveLocale();
18 | }
19 | }
20 |
21 | public function getTranslatableLocales(): array
22 | {
23 | return filament('spatie-laravel-translatable')->getDefaultLocales();
24 | }
25 |
26 | public function getDefaultTranslatableLocale(): string
27 | {
28 | return $this->getTranslatableLocales()[0];
29 | }
30 |
31 | public function getActiveTableLocale(): ?string
32 | {
33 | return $this->activeLocale;
34 | }
35 |
36 | protected function setActiveLocale(): void
37 | {
38 | $this->activeLocale = $this->getDefaultTranslatableLocale();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/SpatieLaravelTranslatableContentDriver.php:
--------------------------------------------------------------------------------
1 | isTranslatableAttribute($attribute);
31 | }
32 |
33 | /**
34 | * @param array $data
35 | */
36 | public function makeRecord(string $model, array $data): Model
37 | {
38 | $record = new $model;
39 |
40 | if (method_exists($record, 'setLocale')) {
41 | $record->setLocale($this->activeLocale);
42 | }
43 |
44 | $translatableAttributes = method_exists($record, 'getTranslatableAttributes') ?
45 | $record->getTranslatableAttributes() :
46 | [];
47 |
48 | /** @var Model $record */
49 | $record->fill(Arr::except($data, $translatableAttributes));
50 |
51 | if (method_exists($record, 'setTranslation')) {
52 | foreach (Arr::only($data, $translatableAttributes) as $key => $value) {
53 | $record->setTranslation($key, $this->activeLocale, $value);
54 | }
55 | }
56 |
57 | return $record;
58 | }
59 |
60 | public function setRecordLocale(Model $record): Model
61 | {
62 | if (! method_exists($record, 'setLocale')) {
63 | return $record;
64 | }
65 |
66 | return $record->setLocale($this->activeLocale);
67 | }
68 |
69 | /**
70 | * @param array $data
71 | */
72 | public function updateRecord(Model $record, array $data): Model
73 | {
74 | if (method_exists($record, 'setLocale')) {
75 | $record->setLocale($this->activeLocale);
76 | }
77 |
78 | $translatableAttributes = method_exists($record, 'getTranslatableAttributes') ?
79 | $record->getTranslatableAttributes() :
80 | [];
81 |
82 | $record->fill(Arr::except($data, $translatableAttributes));
83 |
84 | if (method_exists($record, 'setTranslation')) {
85 | foreach (Arr::only($data, $translatableAttributes) as $key => $value) {
86 | $record->setTranslation($key, $this->activeLocale, $value);
87 | }
88 | }
89 |
90 | $record->save();
91 |
92 | return $record;
93 | }
94 |
95 | /**
96 | * @return array
97 | */
98 | public function getRecordAttributesToArray(Model $record): array
99 | {
100 | $attributes = $record->attributesToArray();
101 |
102 | if (! method_exists($record, 'getTranslatableAttributes')) {
103 | return $attributes;
104 | }
105 |
106 | if (! method_exists($record, 'getTranslation')) {
107 | return $attributes;
108 | }
109 |
110 | foreach ($record->getTranslatableAttributes() as $attribute) {
111 | $attributes[$attribute] = $record->getTranslation(
112 | $attribute,
113 | $this->activeLocale,
114 | useFallbackLocale: filament('spatie-laravel-translatable')->getUseFallbackLocale()
115 | );
116 | }
117 |
118 | return $attributes;
119 | }
120 |
121 | public function applySearchConstraintToQuery(Builder $query, string $column, string $search, string $whereClause, ?bool $isCaseInsensitivityForced = null): Builder
122 | {
123 | /** @var Connection $databaseConnection */
124 | $databaseConnection = $query->getConnection();
125 |
126 | $column = match ($databaseConnection->getDriverName()) {
127 | 'pgsql' => "{$column}->>'{$this->activeLocale}'",
128 | default => "json_extract({$column}, \"$.{$this->activeLocale}\")",
129 | };
130 |
131 | $search = generate_search_term_expression($search, $isCaseInsensitivityForced, $databaseConnection);
132 |
133 | return $query->{$whereClause}(
134 | generate_search_column_expression($column, $isCaseInsensitivityForced, $databaseConnection),
135 | 'like',
136 | str($search)->wrap('%')->toString(),
137 | );
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/SpatieLaravelTranslatablePlugin.php:
--------------------------------------------------------------------------------
1 | defaultLocales;
44 | }
45 |
46 | public function defaultLocales(?array $defaultLocales = null): static
47 | {
48 | $this->defaultLocales = $defaultLocales;
49 |
50 | return $this;
51 | }
52 |
53 | public function getUseFallbackLocale(): bool
54 | {
55 | return $this->useFallbackLocale;
56 | }
57 |
58 | public function useFallbackLocale(bool $useFallbackLocale = true): static
59 | {
60 | $this->useFallbackLocale = $useFallbackLocale;
61 |
62 | return $this;
63 | }
64 |
65 | public function getLocaleLabelUsing(?Closure $callback): static
66 | {
67 | $this->getLocaleLabelUsing = $callback;
68 |
69 | return $this;
70 | }
71 |
72 | public function getLocaleLabel(string $locale, ?string $displayLocale = null): ?string
73 | {
74 | $displayLocale ??= app()->getLocale();
75 |
76 | $label = null;
77 |
78 | if ($callback = $this->getLocaleLabelUsing) {
79 | $label = $callback($locale, $displayLocale);
80 | }
81 |
82 | return $label ?? (locale_get_display_name($locale, $displayLocale) ?: null);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/SpatieLaravelTranslatablePluginServiceProvider.php:
--------------------------------------------------------------------------------
1 | app->runningInConsole()) {
12 | $this->publishes([
13 | __DIR__ . '/../resources/lang' => lang_path('vendor/filament-spatie-laravel-translatable-plugin-translations'),
14 | ], 'filament-spatie-laravel-translatable-plugin-translations');
15 | }
16 |
17 | $this->loadTranslationsFrom(__DIR__ . '/../resources/lang', 'filament-spatie-laravel-translatable-plugin');
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Tables/Actions/LocaleSwitcher.php:
--------------------------------------------------------------------------------
1 | label(__('filament-spatie-laravel-translatable-plugin::actions.active_locale.label'));
21 |
22 | $this->setTranslatableLocaleOptions();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------