How to use us/en instead of en_US with JMSI18nRoutingBundle - symfony

I'm using JMSI18nRoutingBundle for locale routing on our new site, but our existing site uses language + country in the following format and I need to keep the URLs looking the same.
example.com/us/en/hello (en_US)
example.com/be/fr/bonjour (fr_BE)
Is there any way to do this using config? If not, where is the best place to start customizing?

It doesn't look it's possible to do through config, but it can be done by replacing default implementation of PatternGenerationStrategyInterface by your own implementation.
You can check out default implementation that bundle uses here.
After you create your own implementation, just make bundle use your own implementation by setting the config parameter. If you're using YAML for example:
parameters:
jms_i18n_routing.pattern_generation_strategy.class: YourBundle\YourImplementationClass
Hint: you can basically copy/paste from default implementation and change line 69 to use str_replace('_', '/', $locale) instead of just $locale. That way, newly generated route pattern will contain a / if locale contains an _.
Not very elegant solution, but bundle unfortunately doesn't provide enough configuration to make it prettier.

Related

Symfony using multiple translation files for single language

I was wondering if it is possible with Symfony 3.5 to use multiple translation files for a single language when using yml files.
Currently I have something like this:
AppBundle/Resources/translations/messages.en.yml
AppBundle/Resources/translations/messages.de.yml
which contains all my translations in either language. However I was wondering if it was possible to change this to the following structure:
AppBundle/Resources/translations/en/products.yml
AppBundle/Resources/translations/en/invoices.yml
AppBundle/Resources/translations/de/products.yml
AppBundle/Resources/translations/de/invoices.yml
I have been looking but I have been unable to find some kind of solution for this. I got it working for splitting up my routes.
AppBundle/Resources/config/routing.yml
appbundle_routes:
resource: '#AppBundle/Resources/config/routing'
type: directory
Inside that folder I got all my routes split like:
AppBundle/Resources/config/routing/products.yml
AppBundle/Resources/config/routing/users.yml
AppBundle/Resources/config/routing/invoices.yml
I was wondering if it was possible to achieve the same thing with translations?
Symfony's Translator requires files to by named in format domain.locale.loader. In case you have messages.en.yml:
messages is the default name of domain, you can also specify eg. invoices
en is the locale
yml is specifying YAML loader will be used
So your proposed use is not possible to achieve with standard set of configs and functionality. However, you can split your translations to different domain files. So paths would be:
AppBundle/Resources/translations/products.en.yml
AppBundle/Resources/translations/invoices.en.yml
And when you are using translator you specify the domain in which the translation should be looked for:
$translator->trans('translated.key', [], 'invoices');
Or in Twig:
{{ 'translated.key'|trans({},'invoices') }}

How do I localize routes with next.js and next-i18next?

I need to change the name of the route when I change the language. For example, I have a route /en/career but when I change to Czech language, I need a route /cs/kariera. Basically I need the URLs to be localized. Right now, when I'm on /en/career and change language to cs, I get /cs/career. This page should not exist at all and when I render the page on server, I correctly get 404. Can I do something like this with next-i18next package? If so, how?
I found this package https://github.com/vonschau/next-routes-with-locale which probably does exactly what I need but it's apparently no longer maintained and doesn't work under next.js 8.
What I did eventually was to use next-routes package and defined specific route for every page, such as:
module.exports = routes()
.add('en-career-listing', '/en/career/:listing', 'career/listing')
.add('cs-career-listing', '/cs/kariera/:listing', 'career/listing')
.add('en-career', '/en/career', 'career')
.add('cs-career', '/cs/kariera', 'career')
.add('en-our-story', '/en/our-story', 'our-story')
.add('cs-our-story', '/cs/nas-pribeh', 'our-story')
And I also had to create a custom Link component based on next/link where I manually added the language to URL.
next-i18next supports this functionality, it called locale subpaths.
You need to configure: new NextI18Next({ localeSubpaths: 'foreign' }), and then use the Link & Router that NextI18Next instance has on it, not the next/router.

Translations in indexed-search with own templates

I'm using Typo3 8.7.11 and the extension indexedSearch 8.7.11 with Fluid-Templates
I created an extension with my own fluid-templates for the search and search-results form.
Now I also want to use my own translations for these templates. So I created the following files in myTemplateExt/Resources/Private/Language:
locallang.xlf (for the default - en - language)
de.locallang.xlf
fr.locallang.xlf
it.locallang.xlf
Alas, the translations are not loaded.
I found out that I can add the whole path to the translations like
<f:translate key="LLL:EXT:myTemplateExt/Resources/Private/Language/locallang.xlf:sform.submit" />
But then only the locallang.xlf file is loaded. All other languages are ignored.
I also tried to add my own variable to the indexed-search TS-setup:
plugin.tx_indexedsearch.settings.langfile = EXT:myTemplateExt/Resources/Private/Language/locallang.xlf
Which of course fails miserably (most likely because I can't define my own settings-var in TS for another extension?)
Any ideas how I can make the indexed-search extension use my own lang-files?
P.S. I found this suggestion on StackOverflow:
Typo3 Indexed Search Local_Lang path
But this is not what I want - I need more flexibility for my templates, as I need to add some more text than just the regular keys that indexed-search provides to them (yeah, customers, you know ;)
It might not be the best solution, but I solved the problem like this:
I set a variable according to the current language:
<v:variable.set name="currentLang" value="{v:page.language(languages: 'LLL:EXT:myExt/Resources/Private/Language/de.locallang.xlf,
LLL:EXT:myExt/Resources/Private/Language/en.locallang.xlf,
LLL:EXT:myExt/Resources/Private/Language/fr.locallang.xlf,
LLL:EXT:myExt/Resources/Private/Language/it.locallang.xlf',
normalWhenNoLanguage: 'LLL:EXT:myExt/Resources/Private/Language/de.locallang.xlf')}" />
And then for the translation:
<f:form.submit name="search[submitButton]" value="{f:translate(key: '{currentLang}:sform.submit')}" id="tx-indexedsearch-searchbox-button-submit" class="tx-indexedsearch-searchbox-button" />
This isn't elegant, but it works...

reading yaml from twig

Preface: in ez4 i remember there was a tpl function to read ini settings, we used to use this to pass specific locations or id's with which we could then render certain content.
In ezplatform I am now doing the same thing but by using the PreContentViewListener (in the PreContentViewListener read a yml file and pass into the view as params), but this doesn't feel like the correct way as the PreContentViewListener doesn't always get triggered, in custom controllers for example.
Question
Is there a native way to read yaml files from within twig templates? After searching the docs and available packagists i cannot find anything :/
If your needs are simple (i.e. reading container parameters), you can also use eZ Publish config resolver component which is available in any Twig template with ezpublish.configResolver.
You can specify a siteaccess aware parameter in format <namespace>.<scope>.<param_name>, like this:
parameters:
app.default.param.name: 'Default param value'
app.eng.param.name: 'English param value'
app.cro.param.name: 'Croatian param value'
where default, eng and cro are different eZ Publish scopes.
You can then use the config resolver to fetch the parameter in current scope with:
{{ ezpublish.configResolver.parameter('param.name', 'app') }}
If you have Legacy Bridge installed, this even falls back to legacy INI settings if no Symfony container parameter exists:
{{ ezpublish.configResolver.parameter('SiteSettings.SiteName', 'site') }}
Disclaimer: Some say that using config resolver is bad practice, but for simpler usecases it is okay, IMO.
Have a look to our CjwPublishToolsBundle.
https://github.com/cjw-network/CjwPublishToolsBundle
https://github.com/cjw-network/CjwPublishToolsBundle/blob/master/Services/TwigConfigFunctionsService.php
Here we have 2 wrapper twig functions
{{cjw_config_resolver_get_parameter ( 'yamlvariablename', 'namespace default ezsettings') }}
=> ezpublish siteaccessmatching
{{cjw_config_get_parameter( 'mailer_transport' )}}
=> core symfony yaml reader without siteaccess
You could do a lot of things in eZ 4 and not always really good for your application design. ezini was able to read the configuration from the template but now in eZ Platform and by extension Symfony you need to respect more common patterns. IMO the view should not be that smart.
Then injecting variables to the view from a listener (PreContentViewListener or your own) is not a bad idea.
You can also use the Twig Globals that could allow you to do 2 global things:
inject variables (1)
inject a service (2)
Look here: https://symfony.com/doc/current/templating/global_variables.html
(2): please don't inject the service container globally it is bad
(1): I don't remember if the Twig Globals are Site Access aware, if not injecting your own service (2) to manage access to the config might be better.
And finally, I think that the use case is not a common one:
we used to use this to pass specific locations or id's with which we could then render certain content.
Most of the time it is a bad idea to pass ids coming from the configuration to render something, it is much better to organize the content structure to let you pull the location you want using the PHP API. (no id in configuration no hassle with dev, stage, preprod and prod architecture)

Optional part in rails routing path

I am trying to create a route for a page which can have param1 and param2. Param2 is optional part and the code will take a default value if the value is not present. The following is what I am trying to do
match '/school/:dept/:staff/show' => staff#show
match '/school/:staff/show' => staff#show
I have a bunch of statements like the above which seems to be too much of repetition. Is there a better way to do this. This link has an approach using a third party option. Considering it is an older post, looking to see if this is currently supported with rails.
As per: http://asciicasts.com/episodes/203-routing-in-rails-3
We can do this by defining a route like this, directing any matching route to our info#about action. Note that we can nest parentheses when creating optional parameters.
match "/:year(/:month(/:day))" => "info#about"

Resources