What is the best way to add wp language files when deploying? I added a task with wp core language install ...
to the finalize-after.yml
hook for now. Is it possible to include this as a custom hook from deploy-hooks
somehow?
Maybe look into this solution as well: Install&Update wordpress languages with composer.
But yeah, you could use hooks to copy/move files around. Or maybe project_shared_children
too: https://github.com/roots/trellis/blob/2773baa313a496227eafbe294ca5b30d484c232a/roles/deploy/defaults/main.yml#L24-L35
I tried this. It doesnât work (for me).
Would finalize_after
be the right place for this? I was actually wondering if I could - include: myhook.yml
a custom hook file there instead of modifying finalize-after.yml
. Is this possible as the hooks are included themselves?
You mean to make languages shared like uploads? Might be a good idea, but still Iâd like to install languages automatically (and update them after deploy). Maybe an option for language handling built into trellis might make sense?
Iâm not entirely sure whatâs involved in installing/updating language files.
finalize-after
is only required for tasks that require the symlink to be done/deploy finished. This is usually things that actually go through the WP site.
If itâs just copying files it could likely be done before then.
Yeah unfortunately you canât âextendâ a hook we already defined like finalize-after.yml
. Youâd have to define your own hook and copy the contents of that hook and then add your own stuff.
Related threads:
https://discourse.roots.io/t/manage-plugin-translations-current-approaches/9108
https://discourse.roots.io/t/best-practices-extend-an-occupied-hook/9253/1
Iâm using wp-cli for this like:
wp core language install de_DE
I guess the build_after
hook should work as well, wp-cli would only run in the original folder, not the symlinked one, right?
Handling languages as a shared folder might make sense, though, you would only need to run: wp core language update
then after the deploy.
I also want to use this hook - and installing + updating the languages should all happen before symlinking current to this new folder - because otherwise there would be a period of time during language pack installation + update where the site is suddenly in fallback English instead in the selected language.
P.S.: I always also have to run language update for installing the plugin + theme language files.
Yeah build_after
does sound like a good fit for this
Thinking about it, the best way might be to have a shared languages
folder where the desired languages are only installed at the first install (no need to install them over and over again), maybe there could be a check if a core language file exists) and otherwise only run wp core language update
for every deploy. And this should be in the share_after
hook then. Will try this.
Even more ideal would be using composer packages for the language packs of each theme/plugin, currently only those are only available for the most popular plugins/core themes, see Install&Update wordpress languages with composer.
Mabye one could solve this by implementing new composer types which will query the WordPress API directly? It would avoid pulling all possible permutations of plugin/theme version + language pack versions.
As I said, this method didnât work too well for me. Besides the problem with --no-scripts
, on every other deploy or so languages simply did not install. Donât know why. I had to manually delete the files from vendor
on the server and run composer update
to get them installed. Maybe a composer cache problem.
I donât know. Generally youâd just want to add a language and install its files for core and all installed plugins in their current version (if available). Exactly what wp core language update
does. I donât see much sense in dealing with different plugin/language packages and versions here.
I get an error message when trying the command in build-after hook:
- name: Install language de_DE
command: wp core language install de_DE
args:
chdir: "{{ deploy_helper.new_release_path }}"
In build-after:
Error: The site you have requested is not installed.
Run `wp core install`.
fatal: [webstaging]: FAILED! => {"changed": true, "cmd": ["wp", "core", "language", "install", "de_DE"], "delta": "0:00:00.379546", "end": "2017-04-02 14:31:09.035257", "failed": true, "rc": 1, "start": "2017-04-02 14:31:08.655711", "stderr": "Error: The site you have requested is not installed.\nRun `wp core install`.", "stdout": "", "stdout_lines": [], "warnings": []}
It worked for me there as far as I remember. You put the command at the end of the hook file, after composer, right?
Anyway, I went with the shared languages folder now and the share-after hook (which also has the advantage of not having to change the build-after hook). I also added a list var to wordpress_sites.yml for it, so it is configurable and some code that uninstalls languages when they are removed from that list. Works quite well in my tests so far. I can post it here if youâre interested.
Yes, I am very interested in this. I use language packs in multiple sites and deploying changes often.
There you go:
Let me know if it works for you (and if not).
It can be more simple.
In finalize-after hook add at the end of block:
- name: Install WP language es_ES
command: wp core language install es_ES --activate
args:
chdir: "{{ deploy_helper.current_path }}"
- name: Update active language
command: wp core language update
args:
chdir: "{{ deploy_helper.current_path }}"
And in roles/deploy/defaults/main.yml:
project_shared_children:
- path: web/app/uploads
src: uploads
- path: web/app/languages
src: languages
Sharing languages folder the install only work on first deploy and on successive deploys is skipped (by wp-cli).
The second task update (currently active) language for updated core/themes/plugins.
Sure, I had something like this as well, but I donât want this hard-coded into the hook, prefer to have it configurable as a list in wordpress_sites.
Didnât know this, but makes sense. It puts out a warning, though. Itâs no big deal to check for the existance of the po-file, also taught me some Ansible syntax
What ansible code can be added to avoid the warning?
You can have deploy hooks per site:
In âroles/deploy/defaults/main.ymlâ:
deploy_finalize_after:
- "{{ playbook_dir }}/roles/deploy/hooks/finalize-after.yml" # built-in
- "{{ playbook_dir }}/deploy-hooks/sites/{{ site }}-finalize-after.yml"
Then as shown by pacotole further above in this thread,
e.g. for site example.com in âdeploy-hooks/sites/example.com-finalize-after.ymlâ:
- name: Finish WP installation (required for installing languages on initial deploy)
command: wp core install --skip-email --url=www.example.com --title="The WordPress site" --admin_user=theuser --admin_password="the password" --admin_email=info@example.com
args:
chdir: "{{ deploy_helper.current_path }}"
- name: Install WP language es_ES
command: wp core language install es_ES --activate
args:
chdir: "{{ deploy_helper.current_path }}"
- name: Update active language
command: wp core language update
args:
chdir: "{{ deploy_helper.current_path }}"
Edit: I had an error when deploying the first time (to a fresh staging system). The reason was that the WordPress installation has to be finished. I added a wp cli command for this before the command for installing the languages (wp core install --[...]
) (wp core
is idempotent, it wonât reconfigure an existing configured WordPress installation).
Updated approach:
Ensure finished WordPress setup and installing additonal languages in finalize-after site hook:
In case of formal variant languages it can be helpful to also install the non-formal language as a fallback because plugins can be disproportionally translated for the non-formal variant.
https://wordpress.org/plugins/language-fallback/
- name: Install WP (required for installing languages on non-transferred site)
command: wp core {{ project.multisite.enabled | default(false) | ternary('multisite-install', 'install') }}
--allow-root
--url="{{ site_env.wp_home }}"
{% if project.multisite.enabled | default(false) %}
--base="{{ project.multisite.base_path | default('/') }}"
--subdomains="{{ project.multisite.subdomains | default('false') }}"
{% endif %}
--title="{{ project.site_title | default(site) }}"
--admin_user="{{ project.admin_user | default('admin') }}"
--admin_password="{{ vault_wordpress_sites[site].admin_password }}"
--admin_email="{{ project.admin_email }}"
args:
chdir: "{{ deploy_helper.current_path }}"
register: wp_install
changed_when: "'WordPress is already installed.' not in wp_install.stdout and 'The network already exists.' not in wp_install.stdout"
- name: Install WP language de_DE
command: wp core language install de_DE
args:
chdir: "{{ deploy_helper.current_path }}"
- name: Install WP language de_DE_formal
command: wp core language install de_DE_formal --activate
args:
chdir: "{{ deploy_helper.current_path }}"
- name: Update active language
command: wp core language update
args:
chdir: "{{ deploy_helper.current_path }}"
The username / password for WordPress setup can reflect the real credentials (before transferring the database to system, e.g. using a plugin instead, which in turn requires an admin login) are stored in vault.yml
which should be the correct place for secrets:
# Variables to accompany `group_vars/production/wordpress_sites.yml`
# Note: the site name (`example.com`) must match up with the site name in the above file.
vault_wordpress_sites:
example.com:
env:
db_password: "example_dbpassword"
# Generate your keys here: https://roots.io/salts.html
auth_key: "generateme"
secure_auth_key: "generateme"
logged_in_key: "generateme"
nonce_key: "generateme"
auth_salt: "generateme"
secure_auth_salt: "generateme"
logged_in_salt: "generateme"
nonce_salt: "generateme"
admin_user: "wordpress-admin-username"
admin_password: "wordpress-admin-password"
And finally for speeding up and preventing gaps of missing language for longer duration during deploy:
roles/deploy/defaults/main.yml (at line 14):
# There are certain folders you'll want to copy from release to release to speed up deploys.
# Examples: Composer's `vendor` folder, npm's `node_modules`.
# These should not be part of project_shared_children since dependencies need to be atomic and tied to a deploy.
project_copy_folders:
- vendor
- web/app/languages