How to get all translations message domains in Symfony - symfony

TL;DR: I would like to programmatically get all Message Translations Domains of an application made with Symfony 3.4.
An example of expected result:
$domains = $this->get('translator')->getDomains();
//$domains = ['home', 'messages', ...]
But i don't find a method returning application domains in translator service.
Is there an another service returning all application domains?
Thanks!

Ok i found the solution:
$this->getContainer()->get('translator')->getCatalogue()->getDomains();
This solution works for bundles if you store their translations as Symfony 3.4 recommend it : in bundles/Resources/translations/ folder.
Otherwise you should precise the path in in config.yml:
framework:
translator:
...
paths:
- '%kernel.project_dir%/xxx/translations'

Related

Symfony routing configuration I can't find documentation about used to work but now it doesn't

I usually see resource: contain a file path, but here I have a multiline string with yaml instead:
shop_admin_taxon:
resource: |
alias: sylius.taxon
section: shop
templates: AdminBundle:Taxon/Crud
except: ['show', 'index']
redirect: update
grid: shop_admin_taxon
type: sylius.resource
prefix: /
I didn't get any error messagaes about this code when it worked on Symfony 3.2.7 in another project. But now Symfony 3.4 gives me the following error when trying to read this configuration:
The file "alias: sylius.taxon section: shop templates: AdminBundle:Taxon" does not exist.
That's actually expected (since as far as I know you pass a resource locator to resource: and not the actual resource configuration), but why did it work?
Symfony is complex beast and allows a lot of tinkering with it's internals. The routing component is no exception of this and you can see usages which modify or even dynamically create routes on the fly.
This in particular looks like a Sylius extension to routing. If you are curious how precisely it works have a look at the relevant Symfony documentation page. The functionality is being provided by the SyliusResourceBundle with a custom loader.
With all this in mind it looks like you have a broken Sylius install as the custom routing loader is not working. It could be some version mismatch introduced by composer update (e.g. remove component A due to incompatibility with newer version of component B), or bundles not being enabled, or something similar. Make sure all Sylius bundles are installed and enabled

Is it possible to pass a route parameter to a configuration loader in Symfony?

I have an application that requires some per-tenant configuration. What I would like to do is load configuration for specific bundles using parameters embedded in the route:
Route: /{tenantId}/some/resource/390234
where I can then load a configuration specific to $tenantId.
As far as I know this is not possible, since configuration loading in symfony2 happens on compile time.
This means every time you do a
php app/console cache:clear
or cache warmup.
Why not do this via configuration entries via database? As an alternative, use a custom class to load e.g. yaml files (don't forget caching) with your own configuration.

Symfony translations not working

I have done the following checklist:
created translation file respecting format domain.lang.loader
cleared cache
checked that language catalogue is created in cache folder
Though in my twig template file,
{{ 'message'|trans }}
never translates.
Where can I look next in order to make translations work?
Is there any chance that Doctrine Translatable Extension that I am using generates some kind of conflicts?
In Symfony 3.0 I had to clear the cache:
php bin/console cache:clear
I see you already did that, maybe it helps other like me.
Have you enabled the Translator service in your config file?
framework:
translator: { fallbacks: en }
The language catalogue is created in your cache folder irrespective of whether your translator is enabled or not.
Did you try translating in your controller?
$trans = $this->get('translator')->trans('message');
Try to specify domain. If you not specify domain by default it a messages.
{{ 'message'|trans({}, 'some_domain') }}
Then translations can be found in
the kernel root directory/Resources/translations directory;
the kernel root directory/Resources/bundle name/translations
directory;
the Resources/translations/ directory of the bundle.
For example some_domain.fr.yml. Last step is to configure your locale. You can get current locale from request with $request->getLocale()
P.S. try to rm -r app/cache to make sure that the cache is deleted
I could use one of the translations, but not the other and didn't know why. If you have troubles with translations also, read this.
First, standard checklist:
Make sure you enabled and configured translator.
Make sure translation is in proper place and follows proper naming convenction ( domain(messages by default).lang_code.file_format ).
Clear cache using php app/console cache:clear command.
Try to manually call $this->getRequest()->setLocale('en'); in Controller, also you may try to use $this->get('translator')->trans('Some message'); directly in your Controller.
If it still doesn't work, make sure BOM isn't in your translated file. That was my case.
Watch out for BOM in the translated file. The translator who translates the yml file used UTF8 which is OK, but editor he used leaved BOM at the beginning of the file. This is dangerous probably because of PHP's UTF8 BOM bug as it adds few invisible characters to first section of your file.
Btw, debugging your translations may be very helpful, too.
According to the Symfony Translations Documentation page, if you are not using a Service Container for your translation purpose, these are simple steps to go:
Enable and configure Symfony's translation service.
YAML
framework:
translator: { fallbacks: [en] }
PHP
$container->loadFromExtension('framework', array(
'translator' => array('fallbacks' => array('en')),
));
Abstract strings (i.e. "messages") by wrapping them in calls to the Translator ("Basic Translation").
public function indexAction()
{
$translated = $this->get('translator')->trans('Symfony is great');
return new Response($translated);
}
Create translation resources/files for each supported locale that translate each message in the application.
Symfony looks for message files (i.e. translations) in the following default locations:
the app/Resources/translations directory;
the app/Resources/<bundle name>/translations directory;
the Resources/translations/ directory inside of any bundle.
Translation File Name
The filename of the translation files is also important: each message file must be named according to the following path: domain.locale.loader (e.g. filename: navigation.en.xlf):
domain: An optional way to organize messages into groups (e.g. admin, navigation or the default messages) - see Using Message Domains;
locale: The locale that the translations are for (e.g. en_GB, en, etc);
loader: How Symfony should load and parse the file (e.g. xlf, php, yml, etc).
The loader can be the name of any registered loader. By default, Symfony provides many loaders, including:
xlf: XLIFF file;
php: PHP file;
yml: YAML file.
The choice of which loader to use is entirely up to you and is a matter of taste. The recommended option is to use xlf for translations.
Determine, set and manage the user's locale for the request and optionally on the user's entire session.
Clear the cache:
php bin/console c:c
The Translation Process
To actually translate the message, Symfony uses a simple process:
The locale of the current user, which is stored on the request is determined;
A catalog (e.g. big collection) of translated messages is loaded from translation resources defined for the locale (e.g. fr_FR). Messages from the fallback locale are also loaded and added to the catalog if they don't already exist. The end result is a large "dictionary" of translations.
If the message is located in the catalog, the translation is returned. If not, the translator returns the original message.
This helped me to get it worked, since clearing the cache also didn't help.
Symfony 4.6.2:
Try this command to update translation files:
php bin/console translation:update --dump-messages --force de
(Source: https://symfony.com/doc/current/translation.html#configuration)
I can already answer your 2 questions:
1: you can look at
https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php#L97
https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Translation/Translator.php#L174
2: If you're talking about gedmo doctrine extensions, or Knplabs DoctrineBehaviors, no, there is no way it conflicts with symfonys's translator. These are 2 independant pieces.
Just faced the same issue and fixed it by $this->get('translator')->setLocale('fr'); in the controller action. I fixed it by adding {_locale} in the route path.

Detect routes and entities from Symfony2 vendor

i'm creating a bundle that adds an entity and a few routes to be use in a Symfony2 application.
I want my bundle to be used as a vendor, so I've created all the files, published it on GitHub and packagist and everything works fine.
My problem is now when I require the bundle in another project, my entities and my routes are not detected:
1) php app/console doctrine:schema:update doesn't detect any modification
2) When I try to hit a GET route from the vendor, here is the error I get:
No route found for "GET ..."
Any idea is welcome, what's the process to really do these things in a bundle?
Cheers.
Cyril
Take a look at the installation steps of the FOSUserBundle for example. Everyone who uses your published bundle, have to activate it in the appkernel and import the routes. For the entity I think the bundle user have also to subclass the entity.

Symfony 2 multiple apps?

This appears to be the scariest topic relating to Symfony2, as after a week of searching and testing, I am still unable to find an answer to this.
In short, I am building an application that will have several subdomains, and I would like a different configuraton for all of them, while sharing multiple bundles from /src, and more importantly, import central config and routes (As well as each app's own)
I went down the road of creating individual /app directories, AppKernal.php files and bootstrap files. The main issue with this is detailed in another question, which has recieved no answers (not that I blame anyone TBH :D).
Symfony2 multiple config and routing files for subdomain routing
I have found discussion on the matter, Fabian even takes part in this:
https://groups.google.com/forum/?fromgroups=#!topic/symfony-devs/yneojUuFiqw
And this discussion on a PR to github to provide support in version 2.2 (still 6mo away I hear)
https://github.com/symfony/symfony/pull/3378
Is there anyone out there who has done this before? Is the process easy enough to explain? Is there any information available to assist with this?
I'm pretty much at the stage where it appears this simply is not possible. Which I find really strange for a system as touted as Symfony, especially when it appears Symfony1.4 did this rather easily.
Update
Thanks for your responses. The challenge is, there is a hierarchy of configs. These configs in turn import their own routing.yml files.
For instance: the domain http://testing.api.mydomain.com would include the following configs:
config_api.yml -> config_testing.yml -> config_dev.yml -> config.yml
All import their own routing.yml file. But only the one in config_api.yml is loaded. It seems framework: router: config option overrides previous usages in other config files, rather than extends.
In all fairness, the location of the app code is inconsequential. Having a hierarchical configuration with hierarchical routes seems to be the gotacha.
Cheers
Multiple applications projects can be achieved by splitting your code in multiple Kernels.
You can then benefit:
multiple web roots (useful for differents domains)
shared & specific config (via imports)
clean separation of Bundles...
I have described the whole process here: http://jolicode.com/blog/multiple-applications-with-symfony2 and you can find an example distribution here: https://github.com/damienalexandre/symfony-standard
Sorry for necroing...
I just want to say that I have looked into multiple application structure for Symfony2 as well. Since version 2.4, when routing supported hostname based routing, there has been no need for multiple apps.
All you now need to do is separate your "apps" into different bundles, say AcmeSiteBundle and AcmeApiBundle, then in app/config/routing.yml:
acme_site:
host: "www.{domain}"
resource: "#AcmeSiteBundle/Resources/config/routing.yml"
prefix: /
defaults:
domain: "%domain%"
requirements:
domain: "%domain%"
acme_api:
host: "api.{domain}"
resource: "#AcmeApiBundle/Resources/config/routing.yml"
prefix: /
defaults:
domain: "%domain%"
requirements:
domain: "%domain%"
Remember to have domain parameter set in app/config/parameters.yml
parameters:
.....
domain: example.com
You can create different configuration using the testing/Dev example :
Step 1
Create as many web/app.php file as you have subdomain.
web/app_subdomainx.php
Step 2
In each app_subdomain_X.php file change configuration :
$kernel = new AppKernel('subdomainx', false);
Step 3
create configuration file matching your environment
config_subdomainx.yml
security_subdomainx.yml
Step 4
acces you specific domain through
/web/app_subdomainx.php
PS :
Keep config.yml for common configuration (like db connection) and include config.yml into config_subdomainx.yml
imports:
- { resource: config.yml }
you can try to find something on github. I've found the following Bundle which should do this. Imikay RouterBundle
Basically Fabien is right, there's no reason to have more than one application, if you really have a need for a different application it's probably a different project. Bundles and libraries can be easily shared like any other bundle you see on the web.
Then you can have the small part of the set up belonging to each thing you call "app" in the app part of each project.
If they share the entirety of the code then it's just a matter of configuration hierarchy for each sub-domain, which could be your case considering you want to share some part of the config.
Symfony has many ways of allowing you to reutilise code which are very nice, but the framework is not meant to have many applications, if you want to try to hack it, go ahead, but then you're not using the framework anymore. And that's why you can't find examples, not because it's scary, it'd not be that hard to modify, it'd just be ugly, IMO.
Maybe you can try this bundle, that handle multiple domain website on same app and database:
https://github.com/AppVentus/MultiDomainBundle.

Resources