decaporg / decap-cms

A Git-based CMS for Static Site Generators
https://decapcms.org
MIT License
17.79k stars 3.03k forks source link

Support for multilingual content authoring #716

Closed gibujin closed 3 years ago

gibujin commented 6 years ago

The good people at Netlify has confirmed to me that multilingual content is not really supported. But that doesn't necessarily mean that its not possible. For example having a post with a title field * languages supported doesn't really seem like a good idea. Another approach could be to create multiple admin interfaces (/admin/en, /admin/es etc.)for each language (if thats possible, haven't tested it). How would you approach this, any other suggestions?

erquhart commented 6 years ago

If you're looking for multiple languages in the admin interface, there's a PR here that's close: https://github.com/netlify/netlify-cms/pull/403

kations commented 6 years ago

@erquhart I think @gibujin means multilingual content, that would be a nice feature. Maybe there is a way to define languages in config.yml like ['us', 'fr', 'de'] and than you have a global language select in the admin ui to create content for a specific lang.

erquhart commented 6 years ago

In that case I'd expect it to be a bit of both, as selecting a global language setting should cause the UI to be labelled in that language. It sounds like you're looking to have the same content in multiple languages, so I imagine you'd want some way to see what entries exist that have no translation in the current language? Beyond that each language should publish to a separate directory, and we'd need certain string properties in the config to start accepting an object of language-keyed strings.

Thoughts?

tech4him1 commented 6 years ago

@erquhart Is this a duplicate of https://github.com/netlify/netlify-cms/issues/342?

erquhart commented 6 years ago

I think @fool was more pointing at handling automation of translation. This is about supporting the manual creation of multilingual content.

fool commented 6 years ago

Not even "automation" so much as "easy support for". But yes not in the admin gui, in the content. E.g. Being able to take a template from an English post with graphics and code blocks and turning it Spanish. One click "clone" with ability to identify articles that are missing translations would be most of it. Configuring your site to serve the different content would be out of scope for the cms by my reckoning

On Dec 8, 2017 23:56, "Shawn Erquhart" notifications@github.com wrote:

I think @fool https://github.com/fool was more pointing at handling automation of translation. This is about supporting the manual creation of multilingual content.

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/netlify/netlify-cms/issues/716#issuecomment-350431178, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN-oBGRQfIQC0kvYnAkfF8_tI9xkU3Dks5s-j05gaJpZM4P_IL- .

blgo commented 6 years ago

@fool I agree, the clone functionality would be ideal ! It will allow to match the original filename with the translated version.

In addition, It should allow to add a language suffix to the filename: i.e. "mypost.es.md".

However, I realised that I cannot create this suffix ".es" using slug for naming the file because the code remove dots from slug.

Any ideas?

EDIT: I am not requesting a major change, but some configuration that would allow to easily create miltilingual content

erquhart commented 6 years ago

@gibujin you can already create multiple cms instances as you described, since the CMS is just a single page app.

@blgo @fool can you point to any examples out there of a CMS with the described clone functionality?

tech4him1 commented 6 years ago

@blgo The issue with extension suffixes is here: https://github.com/netlify/netlify-cms/issues/877

fool commented 6 years ago

haven't used one but this link makes it seem like maybe drupal and joomla both did it in 2015: https://www.acclaro.com/blog/how-to-choose-cms-for-multilingual-website/

On Dec 20, 2017 10:15, "Shawn Erquhart" notifications@github.com wrote:

@gibujin https://github.com/gibujin you can already create multiple cms instances as you described, since the CMS is just a single page app.

@blgo https://github.com/blgo @fool https://github.com/fool can you point to any examples out there of a CMS with the described clone functionality?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/netlify/netlify-cms/issues/716#issuecomment-353141392, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN-oB2n46-evcyNEO5HSw35Rzkt_YQIks5tCU7AgaJpZM4P_IL- .

erquhart commented 6 years ago

So it sounds like we need product level contributions at this point. So far we have:

Anything missing? UX considerations? How do we make this unobtrusive?

m4rrc0 commented 6 years ago

just dropping my 2 cents. Contentful has a very neat UX for content translation / 'locales'. You may find it inspiring to have a look.

erquhart commented 6 years ago

Great tip @MarcCoet, will do! Feel free to drop specifcs, screenshots, etc if you think any aspect is particularly impactful for the project.

andresgutgon commented 6 years ago

@erquhart do you have a plan in terms of timings to develop multilingual?

erquhart commented 6 years ago

There's no active development at the moment, still need to determine the right approach. You're welcome to help move things along if you're interested in digging in.

whmountains commented 6 years ago

I'm a freelancer in South America 🇨🇱 and almost all my clients need a Spanish site for local clients and an English translation to reach foreign tourists. So having official support for multiple languages would be really useful!

I agree with @MarcCoet that Contentful has a really convenient UI for translations. Basically there are some checkboxes in the sidebar that let you select which languages to work on, and then it will show a copy of each field for each language. Here's a screenshot to show what I mean:

screen shot 2018-03-15 at 7 52 40 pm

IMO an anti-pattern for localization is to simply offer a language switcher with no ability to view multiple languages at once. You have to open multiple windows to see the original text and new text and it's annoying, although still much better than nothing.

erquhart commented 6 years ago

Awesome, thanks for the specifics @whmountains.

@hcavalieri this ^^ just pointed out an issue with the tabbed i18n approach from #1166 - folks are going to want to look at multiple translations at once, especially while translating.

whmountains commented 6 years ago

folks are going to want to look at multiple translations at once, especially while translating.

Exactly. I'm glad you inferred my use-case even though I forgot to state it explicitly. 😄

kizu commented 6 years ago

I would like to link here to my comment in the issue about subfolders content: https://github.com/netlify/netlify-cms/issues/513#issuecomment-384623303 — one of the common patters (used in Hugo, for example) is to have one folder for each post/article/page, and have multiple localised index.LANG.md inside, for example:

├── 2018-04-26-my-awesome-post
    ├── index.en.md
    ├── index.ru.md

How I see this implemented in cms: have multiple tabs for different languages, or even multiple columns, so it would be possible to see same field with different languages next to each other. Similar to how there is a rendered preview for a post, it would be nice to have alternatively compare two languages, with the same sync scroll feature etc.

One issue that also appears related to such handling of content: very often you could want to have some metadata to be duplicated between multiple language versions. This can be true for fields like date (you could want to have it always the same), some attached images (you won't want to attach the same image twice or more), or any other non-textual content (like prices, external links etc.)

How I see this implemented: for each field/widget there can be a boolean param that would tell if that field is by default mirrored across multiple languages. Then, when you edit a page, editting one mirrored field would change others. And there should be a way to “unlink” a field for a page, for example if you'd want to upload a localised image at some point.

moeamaya commented 6 years ago

Craft CMS has clever way of handling this by having a language toggle and small labels on each input. Seems like a decent way to handle the UX.

image

cjonasw commented 6 years ago

Any update on this?

pitometsyurii commented 6 years ago

Yeap, I am interesting in this feature too.

erquhart commented 6 years ago

Update

Until someone is available to dig in (or someone volunteers to own this effort), we could at least ease the pain of multilingual authoring by completing #981 so that an existing entry can be duplicated. To that end, I've added that issue to the 2.0 board targeting the initial release. This doesn't guarantee that it will get in by 2.0, but we'll push.

Comprehensive multilingual support is still a major priority.

fbnlsr commented 6 years ago

I don't know if this could be related, but it could be nice to be able to use a string widget to specify the filename of the page/post being created/edited.

Hugo has a specific behavior where it automatically links two pieces of content when their filename are identical, minus a language parameter. So for instance about.md and about.fr.md are automatically linked on build time.

fbnlsr commented 6 years ago

Just to piggyback on my previous comment: Forestry does provide a way to provide/rename a file from their admin panel. When you create a new content (blog post / page / whatever) you can specify a filename and add your own extension. They then add a small icon with the language prefix of the files in the post list.

rchrdnsh commented 5 years ago

Any updates?

erquhart commented 5 years ago

Not yet, no. Definitely willing to support any devs that are able to work on this, though.

erquhart commented 5 years ago

@schalkventer anything to add here? Does our direction feel on track to you?

schalkventer commented 5 years ago

Thanks for the link @erquhart

So when I'm hardcoding multilingual support currently with Gatsby I do the following. I have a single JSON file be the source of all the translations for a specific item:

{
  type: 'blog',
  id: 'example-title',
  en: {
    title: 'Example Title',
    date: '07/01/2018',
    thumbnail: 'https://placeholder.com/200x200',
    body: 'This an example message'
  },
  af: {
    title: 'Voorbeeld Titel',
    date: '07/01/2018',
    thumbnail: 'https://placeholder.com/200x200',
    body: 'Hierdie is \'n voorbeeld boodskap'
  },
  xh: {
    ...
  },
  so: {
    ...
  },
  fr: {
    ...
  }
}

I would the query a specific language version of that item as follows:

{
  allJson (filter: {  type: { eq: blog }}}) {
    af {
      title
      date
      thumbnail
      body
    }
  } 
}

This will then return an array of all the blog entries in Afrikaans. Seems to work easy enough for now.

However, it becomes a bit tricky when I want to do this with Netlify CMS, since I have to replicate each item in the dashboard for each language. This means the dashboard view for a specific item get pretty cluttered very easily, and just grows in size as more languages or content gets added. I have a project in production at the moment that support 15 languages.

schalkventer commented 5 years ago

So my concern is mostly related to the UX experience in the dashboard (especially if clients need to add the translations themselves). I think @moeamaya's suggestion above in regards to Craft CMS seems pretty solid.

You could possibly define languages in the config.yaml file:

backend:
  name: github
  repo: user/repo

languages
 en: English
 af: Afrikaans
 xh: isiXhosa
 so: Southern Sotho
 fr: French

collections:
  - label: "Blog"
    name: "blog"
    folder: "_posts/blog"
    create: true
    fields:
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Featured Image", name: "thumbnail", widget: "image"}
      - {label: "Body", name: "body", widget: "markdown"}
schalkventer commented 5 years ago

Another approach might be to manually enable translation for specific fields and even have a primary/default language (that will be used for the title, preview, etc.):

backend:
  name: github
  repo: user/repo

languages
 en: English
 af: Afrikaans
 xh: isiXhosa
 so: Southern Sotho
 fr: French

collections:
  - label: "Blog"
    primary_language: "en"
    name: "blog"
    folder: "_posts/blog"
    create: true
    fields:
      - {label: "Type", name: "blog", widget: "hidden", default: "blog" }
      - {label: "Title", name: "title", widget: "string", translations: true }
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Featured Image", name: "thumbnail", widget: "image"}
      - {label: "Body", name: "body", widget: "markdown", translations: true}

So the above might possibly give something like the following (which also solves the problem of identifier_field needing to be a root level field):

{
  type: 'blog',
  date: '07/01/2018',
  thumbnail: 'https://placeholder.com/200x200',
  title: 'Example Title',
  body: 'This an example message',
  af: {
    title: 'Voorbeeld Titel',
    body: 'Hierdie is \'n voorbeeld boodskap'
  },
  xh: {
    title: 'Isihloko Umzekelo',
    body: 'Lo ngumyalezo umzekelo',
  },
  so: {
    ...
  },
  fr: {
    ...
  }
}
schalkventer commented 5 years ago

However, also keep in mind that the above is very specific to my circumstances/tooling, so there might be another approach that might be more useful for the majority of users. Happy to discuss this further.

joallard commented 5 years ago

Interesting approach. I would rather argue that each field could be treated as "localizable/ or not" according to the underlying model, and thus the field would contain the locales:

id: 3072
title:
  en: A Night Not Like the Others
  fr:  Une nuit pas comme les autres
slug:
  en: a-night-not-like-the-others
  fr: une-nuit-pas-comme-les-autres
body:
  en: It was cold outside...
  fr: Il faisait froid dehors...
date: 2019-01-31 16:26 -0500
thumbnail: 'https://placeholder.com/200x200'

Mind you, I'm talking in the abstract here and I'm not exactly familiar with the code base (but I've seen a lot of I18n), but so there could be an interface wrapping reading the values from the column whether or not it is localizable:

// Pseudocode follows
readAttribute(attribute, locale){
  if(this.constructor.isLocalizable(attribute)){
    return readRawAttribute(attribute)[locale]
  } else {
    return readRawAttribute(attribute)
  }
}

Hope that makes sense

schalkventer commented 5 years ago

@joallard Yeah, I like that!

However, as far as I understand identifier_field ( title in this case cannot be an object). I might be wrong though?

joallard commented 5 years ago

Hmm, I'm not sure if I understand identifier_field right, but indeed, there would need to be some kind of unique identifier that's not an object (uuid, serial int, string). Initially I thought that would be naturally the slug, but as the slug often follows the localized title, maybe not. (I'll update my example)

erquhart commented 5 years ago

@joallard do you know of any static site generators that handle localization this way? The examples I'm aware of expect a separate file for each translation for repeatable content like blog posts.

P233 commented 5 years ago

I just created a workaround for this. If you are interested, please take a look at https://github.com/P233/gatsby-netlify-i18n-workaround, and feel free to improve it.

ShevaShen commented 5 years ago

This might help. From Netlify CMS official site. https://www.netlifycms.org/docs/collection-types/#filtered-folder-collections

austincondiff commented 5 years ago

Any update here. This piece of functionality seems crucial to any CMS. I don't think language-based collections are going to cut it. If you have 10 collections and five supported languages, not you have 50 collections to manage! Not too maintainable. This doesn't work.

tremby commented 5 years ago

I've been following this ticket for probably 18 months. This was, and still is, the one thing holding me back from trying netlify-cms out on a new project. I still really want to, but every project which would otherwise be suitable has been multilingual! So I'm still eagerly awaiting this feature.

austincondiff commented 5 years ago

My question is, why isn't this a bigger priority? I am super excited for the JAMstack but this product really needs some love and attention to become a viable replacement in some of these prominent use cases. Does the team need help? Why has this been on the back burner for so long? In general I feel like development with this project is really slow going. Anyone else get this vibe?

whmountains commented 5 years ago

Indeed, I really want to use Netlify CMS but it’s not quite there yet. Proper translation support is the biggest blocker for me.

On Aug 16, 2019, at 15:55, Austin Condiff notifications@github.com wrote:

My question is, why isn't this a bigger priority? I am super excited for the JAMstack but this product really needs some love and attention to become a viable replacement in some of these prominent use cases. Does the team need help? Why has this been on the back burner for so long? In general I feel like development with this project is really slow going. Anyone else get this vibe?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

yvele commented 5 years ago

Yes we also want to use Netlify but lack of multilingual support is a no go for us 😞

whmountains commented 5 years ago

I'm in the same boat.  I think Netlify CMS could be hugely popular but it needs a bit more love.

On September 4, 2019 at 11:54 AM, "Yves M." notifications@github.com wrote:

Yes we also want to use Netlify but lack of multilingual support is a no go for us 😞

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

sangeet commented 4 years ago

I wish there was a solution available for this problem. This is one thing holding a significant amount of potential clients from non-english speaking nations from moving to JAMStack.

Almost all clients need a preview feature from their CMS because Wordpress has spoiled them for a good decade, hence NetlifyCMS is the only viable choice of CMS for Gatsby and the likes because let's be honest nobody is willing to pay $600/year for Gatsby Preview feature that they sell. So NetlifyCMS it is and it works great.

Now, it all falls apart when the potential client is from a non-english speaking nation. Then they at the very least absolutely need at least support for two languages. There are currently only two headless CMS which offer reasonably good locale features, Contentful and DatoCMS, but then these two lack the preview feature and as usual clients are not willing to spend $600/year for adding preview support to them.

So essentially, for most of the potential clients from non-English speaking nations willing to move to JamStack, this is one thing significantly holding them back. They need a combination of preview feature + content localization and at the moment nothing offers this essential combination and I feel that it is seriously hurting the adoption of JAMStack in general for a lot of potential clients.

I can understand that it is not easy to build up such a feature on an already very active project, but Netlify has significant resources behind it and hence it shouldn't be impossible to prioritize this feature because as it currently stands, lack of localization is a deal breaker for a lot of clients and at the moment there's no real way around it unless they are willing to sacrifice on preview feature which a majority of clients are not.

Sorry if this went slightly off topic, just expressing my views on the significantly important need of this essential feature for a CMS.

chriskirknielsen commented 4 years ago

I have started a tiny bit of work on this idea but I will warn you:

If anyone wants to join in on the fun, I have created a branch: https://github.com/chriskirknielsen/netlify-cms/tree/feature/path-options

If you run this locally you will see both the English and French test posts listed in the Posts collection. A first step! (we can address mixed sorting later)

The config.yml file has new/edited settings:

# ...
    path_options:
      language:
        - en
        - fr
    folder: '_posts/{{ language }}' # any {{ template }} must match one of the `path_options`
    internal_routing: 'posts/{{ language }}' # Override the route URL, ie.: /admin/collections/:internal_routing/edit
# ...

Right now I've hit a roadblock since I don't know how NetlifyCMS handles all of its routing and commits updates… I have added an option in the collection named internal_routing which will allow NetlifyCMS to read the extra path options in the right sequence (so that if the post is in /en:non-code/slug, it'll know to look for {{ language }}, and for {{ tag }} — you don't want tags in your slug but just an example — or maybe it should be /language/en/tag/non-code?). For now that's implemented in one spot with commit ac2d1fa but any help to get this working everywhere would be great!

I'd love to get some insight from people who are more involved in this (type of) project and that might be able to provide better insight as to how this all works. Any help at all would be awesome. :)

Thanks!

EDIT: Managed to get the routing to work, under the condition that, if multiple path options are used, they should be separated by a :.

erquhart commented 4 years ago

I’ll at least note that this issue is very much top of mind for the maintainers. It’s the 4th highest issue in our list sorted by reactions (thumbs up really do matter): https://github.com/netlify/netlify-cms/issues?q=is%3Aopen+sort%3Areactions-%2B1-desc

Big thanks to everyone that is working toward intermediate solutions, you’re helping to bridge a critical gap.

Sent with GitHawk

phil-lgr commented 4 years ago

I just created a workaround for this. If you are interested, please take a look at https://github.com/P233/gatsby-netlify-i18n-workaround, and feel free to improve it.

this is great! I'm wondering if this is a direction considered by the maintainers?

hajaalin commented 4 years ago

A related point about Hugo, currently the only way to translate section names seems to be this workaround: https://github.com/gohugoio/hugo/issues/3354#issuecomment-475975122.

It would be great to have support for this use case, i.e. ability to specify content directory per language, and to add a shared translation key (e.g. slug of default language).

barthc commented 4 years ago

So we have a PR #2988 that attempts to solve this issue. The approach is based on comments https://github.com/netlify/netlify-cms/issues/716#issuecomment-373549215 and https://github.com/netlify/netlify-cms/issues/716#issuecomment-459513051 . Any feedback is highly appreciated, thanks.