getkirby / kirby

Kirby's core application folder
https://getkirby.com
Other
1.31k stars 168 forks source link

strftime in the panel ignore local setting with toDate() #1872

Closed yoanmalie closed 5 years ago

yoanmalie commented 5 years ago

Describe the bug With the strftime date handler, the date is not translated when used in the panel.

To Reproduce Steps to reproduce the behavior:

  1. Clone the starterkit

  2. Change the date handler in the config for strftime

    'date' => [
    'handler' => 'strftime'
    ],
  3. Edit the info key in the sections/notes.yml blueprint for: info: "{{ page.date.toDate('%A %d %B %Y') }}"

  4. Go to the panel and install it in French.

Expected behavior Date should be translated in French, like Mercredi 31 octobre 2018, Vendredi 05 octobre 2018, Mercredi 26 Septembre 2018…

Screenshots

The notes list in the Kirby panel

Kirby Version Tested on 3.1.3 and 3.1.4.

Additional context The date handler with the same toDate() I used work well in a template.

PaulMorel commented 5 years ago

This might not be Kirby related. Do you have the language packs installed on the server? By default most servers don't come with french language packs, so strftime defaults to english.

For example in my setup, a Ubuntu 18.04 LTS LAMP Stack, I have to install the language-pack-fr package for french dates to work correctly with strftime.

It should be the same with other languages. Hopefully this helps! Bonne chance!

yoanmalie commented 5 years ago

Hi @PaulMorel Thank you for explaining! The fact is that if I use the same toDate() but in a page template, it work well. So that would say the language pack is here, right ?

PaulMorel commented 5 years ago

I would say if it works on the front-end, but doesn't on the back-end, it's not a language pack issue.

But, I can't reproduce your problem. Tested on 3.1.3

I added {{ page.date.toDate('%A %d %B %Y') }} in the panel and works for me, but only after I installed the Ubuntu language pack and restarted Apache.

Page

image

Section

image

Front-end

image

One last thing, what does your /site/languages/fr.php look like? Here's mine:

<?php
return [
  'code' => 'fr',
  'default' => true,
  'direction' => 'ltr',
  'name' => 'Français',
  'locale' => 'fr_CA.utf-8',
  'url' => '/'
];

The locale option is whats important for strftime to work correctly. I'm in Canada so I use fr_CA. So you the locale appropriate for you. fr_BE, fr_CH, fr_FR, etc.

yoanmalie commented 5 years ago

Oh I missed this part, but there a new bug here?

By adding this I litterally have nothing:

image

site/languages/fr.php:

<?php
return [
  'code' => 'fr',
  'default' => true,
  'direction' => 'ltr',
  'name' => 'Français',
  'locale' => 'fr_FR.utf-8',
  'url' => '/'
];

also, in site/config/config.php:

<?php
return [
    'languages' => true,
];

I forget to mention it in the first post but my locale are also set like this:

return [
  'locale' => [
    LC_COLLATE => 'fr_FR.UTF-8',
    LC_MONETARY => 'fr_FR.UTF-8',
    LC_NUMERIC => 'fr_FR.UTF-8',
    LC_TIME => 'fr_FR.UTF-8',
    LC_MESSAGES => 'fr_FR.UTF-8',
    LC_CTYPE => 'fr_FRs.UTF-8'
  ]
]

This is not working yet with the new Kirby 3.2.0.

PaulMorel commented 5 years ago

If your website is only in french, you don't need 'languages' => true in your config.php. If I remember correctly 'languages' => true, is for multi-language websites.

Your locale should be in fr.php. Eithe

<?php
return [
  'code' => 'fr',
  'default' => true,
  'direction' => 'ltr',
  'name' => 'Français',
  'locale' => 'fr_FR.utf-8',
  'url' => '/'
];

or

<?php
return [
  'code' => 'fr',
  'default' => true,
  'direction' => 'ltr',
  'name' => 'Français',
  'locale' => [
    LC_COLLATE => 'fr_FR.utf-8',
    LC_MONETARY => 'fr_FR.utf-8',
    LC_NUMERIC => 'fr_FR.utf-8',
    LC_TIME => 'fr_FR.utf-8',
    LC_MESSAGES => 'fr_FR.utf-8',
    LC_CTYPE => 'fr_FR.utf-8'
  ]
  'url' => '/'
];

I think these two are equivalent.

yoanmalie commented 5 years ago

I tried both solution, with or without'languages' => true. As soon as I create a fr.php file, the dates in the panel disappear…

texnixe commented 5 years ago

Just to clarify: A Kirby site with languages defined in the /languages folder is a multi-language installation. The config setting allows/prevents adding/deleting languages via the Panel.

distantnative commented 5 years ago

@yoanmalie

Go to the panel and install it in French

Are you using the Panel in French (so your Panel user language is set to French in the user settings) or are you editing the French translation of your site?

yoanmalie commented 5 years ago

@distantnative I use the panel in French, and it work. In the first screen, "Add" is well translated to "Ajouter".

distantnative commented 5 years ago

The tricky part here is: Should the Panel call the API in the language

a) the Panel is used in, or b) the content from the API should be in?

With your case it's a mixed thing: you are editing a content language and the API needs to respond to that but at the same time it should also reflect the lanuage of the Panel user...

not sure if we can get that.

lukasbestle commented 5 years ago

I think it should always use the user language as it's a piece of UI, not a piece of raw content like the other multilang content.

distantnative commented 5 years ago

But this is very hard: The Panel is not aware of the difference between a query like {{ page.date.toDate('%A %d %B %Y') }} and {{ page.subtitle }}. For the Panel both are a query to be evaluated by the backend. However, in the latter case it's clear that we want a result based on the current content translation – not based on the Panel user language. So having a different expectation for the former is a tricky exception to the rule.

Making toDate always react to the user language doe snot work either IMO. Imagine a frontend that works with logged in users but still wants to keep its site versions in language A and language B separated. Would be weird that the user gets its Panel language there no matter whether being on language A or language B site.

Conceptually, maybe adding a third parameter could work. Something then like {{ page.date.toDate('%A %d %B %Y', null, user.language.code) }}. What do you think?

texnixe commented 5 years ago

@distantnative Your last suggestion sounds like a good idea, that would at least leave it to the developer to decide.

Personally, I would expect the info to be in the currently selected language, not the Panel user language. But that is probably really a question of everyone's perspective.

lukasbestle commented 5 years ago

The Panel is not aware of the difference between a query like {{ page.date.toDate('%A %d %B %Y') }} and {{ page.subtitle }}. For the Panel both are a query to be evaluated by the backend.

But does the backend need to know about the intent of the specific query to be able to parse them? The difference between a method call in the frontend and a query in the Panel is that the latter gets requested via the API. So what we could do is to set the PHP locale to the language of the current user whenever an API request is processed. The frontend would be completely unaffected.

@distantnative However, in the latter case it's clear that we want a result based on the current content translation – not based on the Panel user language. So having a different expectation for the former is a tricky exception to the rule. @texnixe Personally, I would expect the info to be in the currently selected language, not the Panel user language. But that is probably really a question of everyone's perspective.

I think that's exactly the issue. I would expect the Panel to show the content of the language, but in the format of the UI while you would expect the format to match the content language as well.

So maybe the option to override the language would make sense here. I'm not sure however if this should be a param to the toDate() method, because that would then also be there for calls from the frontend (where such an override doesn't often make sense). Also it would need to be passed in every location where toDate() is used in queries. What about a global Kirby option that defines whether locales in API requests should be set based on the content or user language? The option would default to "user language" (so that it works on single-lang sites as well), but could be set to "content language" if needed.

distantnative commented 5 years ago

But I still get how you would differentiate {{ page.date.toDate('%A %d %B %Y') }} and {{ page.subtitle }} in your example. I assume that both types are used intermixed in projects. For the one you want to use the Panel user language, for the other the content translation language.

As I see it, we can run Kirby (as in running an API request) only in one language. There is no differentiation between, run it in language A for retrieving content and in language B in regard to date formats.

Also consider this potential case: the date field of {{ page.date.toDate('%A %d %B %Y') }} is actually translatable, so you have a different value for language A as for language B which the API has to deliver according to the current active content translation in the Panel. But then you want it also to format it according to the Panel user language, which could be language C.

distantnative commented 5 years ago

Just to make it clear, I totally understand where you are coming from and think the intention makes sense (also as @texnixe pointed out, this might be a lot about taste as well). But my main point is that I don't think we can achieve this with the current Kirby architecture. Or at least I have no idea how we could.

lukasbestle commented 5 years ago

But I still get how you would differentiate {{ page.date.toDate('%A %d %B %Y') }} and {{ page.subtitle }} in your example. I assume that both types are used intermixed in projects. For the one you want to use the Panel user language, for the other the content translation language.

I think you are mixing two things here:

So by setting the PHP locale for API requests based on the user language, we only ever change the "language for formatting". We do not change which data is retrieved from the content files. And because we don't change that, the Panel doesn't ever need to differentiate between querying simple fields or dates. In both cases it would get the content field from the currently active text file. The formatting happens later when the toDate() method is called.

distantnative commented 5 years ago

But can we set a different PHP locale for API request that differs from the content language we request? My point was exactly that I don't think we can.

lukasbestle commented 5 years ago

Why not? The API knows which user sent the request based on the session or basic auth and can therefore grab the user language.

bastianallgeier commented 5 years ago

@lukasbestle think of this example:

The help text in a pages section might include some dynamic information – maybe such a date – which should be in the current interface language, but the content language could still be set to something different. Thus the page titles in the pages section should be in the content language. But we don't send two requests for that. It's a single API request, which fetches the section data and the section options.

distantnative commented 5 years ago

@bastianallgeier But I think Lukas is actually right: If we set the Panel user interface language as locale but still pull the content translation language, we achieve both: We get the content values for the currently edited content translation, but the format that is displayed via strftime is that of the interfact locale.

lukasbestle commented 5 years ago

Yes, exactly. The only thing the PHP locale does is to change the format for strftime(). Everything else is unaffected and handled like before.

bastianallgeier commented 5 years ago