Organizing country-specific and multilingual content

saramaloney
saramaloney Vanilla Ice Cream
edited March 10 in Talk Community #1

In April, we'll be expanding our community to many more global members than we do today. I would say about 90% of our community's content is relevant to all users, regardless of what country they live in, but 10% may only be relevant to to you depending on the country you reside in.

I'm thinking we'll use a tagging structure to tag content that is specific to a certain country (eg. #Australia), but I'm wondering if anyone has best practice or other tactics to share for organizing this type of content?

Also, is there an ability in Vanilla to limit users to only using tags that we set? Or can users always just tag whatever they want?

TIA!

Comments

  • Shauna
    Shauna HLV Staff

    @saramaloney will most of the new international users be English-speaking, or are you looking at multi lingual content?

  • saramaloney
    saramaloney Vanilla Ice Cream

    @Shauna For the launch in April, English-speaking. Long term, multilingual.

  • Shauna
    Shauna HLV Staff

    Cool, I'm interested to see what other community members have to say here, but if the vast majority of content is relevant for everyone and only 10% is country specific, I think I would go with tags. If the volume of content becomes such that it needs its own category or even subcommunity, you could always move that content after the fact (potentially with automation rules by the time you get to that critical mass).

    For this part

    >Also, is there an ability in Vanilla to limit users to only using tags that we set? Or can users always just tag whatever they want?

    Today, you can choose who can create new tags, but if tagging is on all users can tag content with all already-created tags—- but the ability to control who can use what tags more granularly is something we've been considering for later this year (no timeline right now though).

    Similar to these ideas:

  • saramaloney
    saramaloney Vanilla Ice Cream

    Thanks, Shauna! This is all really helpful.

  • Alex Dunne
    Alex Dunne Vanilla Flower

    Hi @saramaloney ,

    I run a community with customers in 3 different countries and there's certain content we need available to users in US and Canada but hidden from our Australian users. For that, we've had to utilize roles and categories to manage that. It's a bit fiddly at times and prone to human error (for example, someone posted about a giveaway to the full community when it's only for NA users and that caused a bit of a headache) but it does work. I'd love if there was a way to decide at the post level who gets to see it.

  • saramaloney
    saramaloney Vanilla Ice Cream

    @Shauna Hi! Is there a publicly available Vanilla client site that uses the multilingual addon that you could direct me to? We are considering moving away from using subcommunities for different languages and instead using the multilingual addon.

    Also, I'm wondering if you've seen any customers embed a language translator on their community in order to mimic the Google Translate experience in order to translate user-generated content on a page:

  • LiselotteP
    LiselotteP Vanilla Ice Cream

    Also interested in this, I'm exploring options to making a full French site, and full Japanese website.

  • paddykelly
    paddykelly HLV Staff

    There does exist a JavaScript widget called Website Translator made by Google Translate that will allow users to choose a language from a dropdown and have the text of a site translated on the fly. Sounds too good to be true? It sort of is. If you read this post from 2020, that says they wanted to discontinue it but decided to leave it up for non-commercial use due to the pandemic (so there's one good thing that came out of the pandemic). That said, it still functions. For a demo of how it works: https://paddykelly.vanillastaging.com/

    The code goes right in the JavaScript of the Theme:

    /**
     * Get the current nonce from scripts in the head.
     **/
    
    const getNonce = () => {
        const scripts = document.querySelectorAll('script');
        for (let i = 0; i < scripts.length; i++) {
          if (scripts[i].nonce) {
            return scripts[i].nonce;
          }
        }
        console.warn('Failed to retrieve a nonce. Check to see if your scripts work.');
    };
    
    const NONCE = (document.querySelector('script')?.nonce) ? document.querySelector('script')?.nonce : getNonce();
    
    /**
     * Add style tag to the head.
     * 
     * @author Patrick Kelly <pkelly@higherlogic.com>
     *
     * @params styles String Valid CSS styles.
     */
    const injectCSS = (styles) => {
      const head = document.querySelector('head');
      const styleTag = document.createElement('style');
      styleTag.innerHTML = (styles) ? styles : '';
      head.appendChild(styleTag);
    }
    
    
    /**
     * Add JavaScript into the head.
     * 
     * @author Patrick Kelly <pkelly@higherlogic.com>
     *
     * @params script String Valid JavaScript scripts.
     */
    const injectJS = (script) => {
      const body = document.querySelector('body');
      const scriptTag = document.createElement('script');
      scriptTag.setAttribute('nonce', NONCE);
      scriptTag.innerHTML = (script) ? script : '';
      body.appendChild(scriptTag);
    }
    
    
    /**
     * Add HTML into the body.
     * 
     * @author Patrick Kelly <pkelly@higherlogic.com>
     *
     * @params what String Valid HTML.
     * @params where String Existing DOM element where you will put it.
     */
    const injectHTML = (what, where, position) => {
        const targetPosition = position ?? 'beforebegin';
        const target = document.querySelector(where) ?? document.querySelector('body');
        target.insertAdjacentHTML(targetPosition, what);
    }
    
    /**
     * Add JS into the head.
     * 
     * @author Patrick Kelly <pkelly@higherlogic.com>
     *
     * @params validUrl The URL to the JavaScript file to be included.
     */
    const injectJSFile = (validUrl) => {
      const body = document.querySelector('body');
      const scriptTag = document.createElement('script');
      scriptTag.setAttribute('nonce', NONCE);
      scriptTag.async = true;
      scriptTag.src = (validUrl) ? validUrl : '';
      body.appendChild(scriptTag);
    }
    
    const googleTranslateScript = `
        function googleTranslateElementInit() {
            new google.translate.TranslateElement({
            pageLanguage: 'en',
            layout: google.translate.TranslateElement.InlineLayout.VERTICAL
            }, 'google_translate_element');
        }
    `;
    
    const googleTranslateSrc = 'https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit';
    
    const googleTranslateHtml = `
        <div class="google-translate-wrapper">
          <!-- GOOGLE TRANSLATE START -->
        <div id="google_translate_element"></div>
          <!-- GOOGLE TRANSLATE END -->
        </div>
    `;
    const googleTranslateCss = `
        .google-translate-wrapper {
            min-height: 60px;
            top: 68px;
            right: 20px;
            text-align: right;
            position: absolute;
            display: inline-block;
        }
        #google_translate_element {
            max-width: 300px;
            margin: auto;
            text-align: left;
        }
        .skiptranslate.goog-te-gadget, a.skiptranslate.goog-te-gadget {
        text-shadow: 0 0 3px #fff;
        color: black;
    }
    `;
    onVanillaReady(() => {
      window.addEventListener('load', () => {
          injectCSS(googleTranslateCss);
          injectJS(googleTranslateScript);
          injectHTML(googleTranslateHtml, '.headerNavigation', 'afterend');
          injectJSFile(googleTranslateSrc);
      });
    });
    

  • paddykelly
    paddykelly HLV Staff

    Here's a link to the Google Translate article I referenced 👆️. https://developers.google.com/search/blog/2020/05/google-translates-website-translato

  • LiselotteP
    LiselotteP Vanilla Ice Cream

    This is interesting… but how would that work if users want to post in different languages?

    In an ideal world, I want the above (users to be able to translate the main English website), but also set up subcommunities for example who's "home" language would be French or Japanese for example.

  • Shauna
    Shauna HLV Staff

    Hey @saramaloney — I couldn't find anyone public using the multi lingual addon (but tons using subcommunities)…

    Personally, I have not found the multilingual feature super useful unless used with a very bilingual community (for example, a lot of people here in Northerneastern Ontario close to the Quebec border speak a log of frenglish and switch languages mid sentence haha).

    For communities that aren't largely bilingual or multilingual, however, I'm not sure if this addon is a great user experience as I would see the OOB Vanilla buttons in my language, but any user generated content would still appear in another language, which could be confusing.

    Now the second part of your question might make this a better user experience — using the google translate functionality. It's not a public site but I think that @thaas played with this on his community — did you end up keeping it? Do people like it? Would you be able to share how you did it with @saramaloney

    Historically, we have stayed away from translating user generated content as forum posts as (historically) services like google translate have had a hard time translating the nuance of forum posts correctly (especially more casually written forum posts that use slang, whereas articles tend to be more straightforward in language and easier for non human translations), but this is something we may re-explore as translation tech gets better. Stay tuned on this front.

    At the end of the day, I think subcommunities tends to be the right choice for most communities, but I am super interested to hear how folks are managing multi lingual communities and what level of interest there is in either revamping the multilingual addon or putting more effort into exploring machine translation options.

    Shauna

  • saramaloney
    saramaloney Vanilla Ice Cream
    edited March 13 #13

    @thaas Any advice or just insight into your experience here would be greatly appreciated!

    I hear what you're saying @Shauna about translating UGC imperfectly - we're okay with this flaw for now for the sake of being able to say that our community can support people communicating in the 44 languages that the Vanilla multilingual add-on can support.

    I would definitely appreciate some exploring of machine translation options, or at least an integration with a third party tool that could do it!

    Thank you for your response!

  • saramaloney
    saramaloney Vanilla Ice Cream

    @paddykelly Sorry, somehow I missed your response here - thank you for sharing how you did this! I copy/pasted your code into the Javascript of our staging site theme - nothing happened. Is it as simple as copy/paste? I do not work with code, so I'm sure this is a silly question, but appreciate your help.

  • paddykelly
    paddykelly HLV Staff

    Hey @saramaloney the code works like a charm. You did good. There was maybe something I forgot to mention. When you inspect the page with the developer tools you see this error:

    That is telling us that the browser refused to load the Google script for security reasons. You have to tell our application, to tell the browser that it's OK to load scripts from the domain googleapis.com. We thought about that, too. In the Dashboard under security you simply add the domain here:

    The "*" means any script coming from googleapis.com or any of its subdomains (in this case translate-pa.googleapis.com). I save it. And voilá:

  • saramaloney
    saramaloney Vanilla Ice Cream

    @paddykelly Thank you! It does really work like a charm.