∅ the empty set

Squarespace 6 localisation

squarespace-logo-horizontal-white.jpg

I don't know about you, but I am hearing a lot about Squarespace these days, either at conferences or as a podcast sponsor, and I decided to evaluate v6 from an internationalisation angle.

Squarespace shines as a CMS. Really. Its approach to designing layouts and organising pages is amazing. The templates you have to choose from are very well designed, and you can customise most of it from the client interface. I won't go into the details her, but you can find numerous reviews elsewhere.

It felt as the perfect solution for those small budget websites projects. Build on an existing template with the client to meet their needs and expectations. Sounded great.. until you get to the localisation issues.

I didn't expect Squarespace to offer an localised version of their admin interface, but I did expect them to take into account the website's localisation settings set in “Time / Geography”.

sq_datetime_settings_tm.png

As from I can see, this is only used in the lang parameter of the html element. I would expect them to use it to format the blog's dates and times and to initialise the YUI 3 Library Y.config.lang variable. But sadly, no.

Typically, the Calendar widget (template block) couldn't be used on a French site:

sq_calendar_01.jpg

So, I tried to figure out what could be done via CSS and JavaScript. There are a number of similar request in Squarespace's forum for translation of the basic wording and date formating used in the blog, but very few answers.

Code injection

The following snippets work on the Template “Five” and have not been tested on the others. Your mileage may vary depending on their markup…

I first tried to set the correct localisation (French) for JavaScript widgets such as the Calendar by injecting code into the main page header (situated in Settings > Code Injection):

<script>
Y.use("lang/datatype-date-format_fr-FR",
  function(Y) {
      Y.Intl.setLang("datatype-date-format", "fr-FR");
  }
);
</script>
sq_calendar_01.jpg

Unfortunately, this only translates the month name, not the short weekdays which remain in English, so I added a line of CSS to hide them:

/*
  Hide YUI3 Calendar weekdays
*/
table.yui3-calendar-grid thead {
  display:none;
}

The Calendar widget looked acceptable now for a French public:

sq_calendar_01.jpg

This approach didn't have any effect on the blog entry dates. I wrote a small JavaScript snippet injected into the page footer to basically translate the month name and change the format from <month day, year> to <day month year>.

<script>
/* List of months in French */
var month = new Array(12);
    month[0] = "janvier";
    month[1] = "février";
    month[2] = "mars";
    month[3] = "avril";
    month[4] = "mai";
    month[5] = "juin";
    month[6] = "juillet";
    month[7] = "août";
    month[8] = "septembre";
    month[9] = "octobre";
    month[10]= "novembre";
    month[11]= "décembre";

Y.use('node', 'node-load', function(Y) {
  Y.on('domready', function() { 

    /* (1) Reformat blog entries published dates */
    Y.all('time.published').each(
      function() {
      var pdate = new Date(this.getAttribute('datetime'));
      this.setHTML(pdate.getDate() + " " 
          + month[pdate.getMonth()] + " " 
          + pdate.getFullYear());
      }
    );

  });
});
</script>

This hack worked nicely for plain dates, but not for blog listings where Squarespace uses “time since” dates like “3 months ago”, so I substituted that string with the blog entry's date with the following snippet:

    /* (2) Replace time since strings with published dates */
    Y.all('time.timestamp').each(
      function() {
        var tdate = new Date(this.getAttribute('datetime'));
        this.setHTML(tdate.getDate() + " "
        + month[tdate.getMonth()] + " "
        + tdate.getFullYear());
      }
    );

String substitution

Similarly, you can replace specific words/sentences by their French counterpart via JavaScript code injection in the footer:

  • Share -> Partagez
  • Read more -> Continuer à lire
  •   Y.all('.ss-social-button').setHTML('Partagez');
      Y.all('.inline-read-more').setHTML('Continuer à lire');
    

    A blog entry will then look like this:

    sq_string_replacement.png

    The CSS still needs to be tweaked, but we are getting closer to what I expected.

    Developer Platform

    Version 6 offers a Developer Platform which enables you to create your own Squarespace template from scratch. Morevoer, it is completely free until you are ready to publish so get started! Kudos for that. Unfortunately, you can't edit the template blocks (yet, says the documentation), so the same hacks apply.

    Keep in mind we are hacking your way to a solution, this code will have to be removed once Squarespace formats dates according to the user's settings.

    Ø permalink: https://davidroessli.com/logs/2013/04/squarespace_l10n/


Reponses to “Squarespace 6 localisation”

#1 by Joona Mäkinen

09:53 on 18 June 2013

David, thanks very much for your helpful tip!

I used your code to translate the date format in to finnish, and it worked perfectly.

For some reason, though, I can't get the "substitute specific strings" part of your code to work. I'm trying to translate "Newer" and "Older" in the blog, but the default ones stay anyways. Do you have an idea, why it doesn't work? I used your example code from SQS Answers forum, and just replaced french words with finnish equivalents.

Here's my code:

:::::::::::::::::::::::::::::::::::::::::::::
::: Substitute specific strings
*/
Y.all('.ss-social-button').setHTML('Partagez');
Y.all('.inline-read-more').setHTML('Lue lisää');
// Y.all('.newer-posts').setHTML('Seuraava');
// Y.all('.older-posts').setHTML('Edellinen');
/*


#2 by David Roessli

09:58 on 18 June 2013

@Joona Thanks :)

Try uncommenting the two last lines in your code:

/*
:::::::::::::::::::::::::::::::::::::::::::::
::: Substitute specific strings
*/
Y.all('.ss-social-button').setHTML('Partagez');
Y.all('.inline-read-more').setHTML('Lue lisää');
Y.all('.newer-posts').setHTML('Seuraava');
Y.all('.older-posts').setHTML('Edellinen');

#3 by Joona Mäkinen

10:07 on 18 June 2013

Thanks for your quick reply!

I tried that, but unfortunately it didn't work..

#4 by Jan Schuhfuss

18:11 on 25 July 2013

Try to insert the code within the domready-event. For me the following code did the job:

Y.use('node', 'node-load', function(Y) {
  Y.on('domready', function() { 
  ...
  /* (1) Reformat blog entries published dates */
  ...
  /* (2) Replace time since strings with published dates */
  ...
  /* Substitute specific strings */
  Y.all('.ss-social-button').setHTML('Teilen');
  Y.all('.inline-read-more').setHTML('Weiterlesen');
  Y.all('.newer-posts').setHTML('Neuere Beiträge');
  Y.all('.older-posts').setHTML('Ältere Beiträge');
  Y.all('.comments').setHTML('Kommentare'); 
  });
}); 

#5 by Christoph

10:42 on 17 September 2013

David, thanks a lot for this excellent article. Everthing worked well for me expect setting the localisation to German.

I added to following snippet to Settings - Code Injection - Header):


Y.use("lang/datatype-date-format_de-DE",
function(Y) {
Y.Intl.setLang("datatype-date-format", "de-DE");
}
);

Unfortunately this did not change anything in the calendar widget. Months names are still displayed in English.

#6 by Uwe Stöhr

05:41 on 7 February 2014

The code doesn't work for me as of February 2014. The calendar is still in English and e.g.
table.yui3-calendar-grid thead {display:none;}
does not hide the days.

I therefore designed new code to fix the calendar list layout for German:
Any comment is welcome!

<script src="//code.jquery.com/jquery-1.10.2.js"></script>

<script>
// load a function to replace strings
/*
* jQuery replaceText - v1.1 - 11/21/2009
* http://benalman.com/projects/jquery-replacetext-plugin/
* Copyright (c) 2009 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($){$.fn.replaceText=function(b,a,c){return this.each(function(){var f=this.firstChild,g,e,d=[];if(f){do{if(f.nodeType===3){g=f.nodeValue;e=g.replace(b,a);if(e!==g){if(!c&&/</.test(e)){$(f).before(e);d.push(f)}else{f.nodeValue=e}}}}while(f=f.nextSibling)}d.length&&$(d).remove()})}})(jQuery);
</script>

<script>
var monthDE = [];
monthDE[0]="Januar";
monthDE[1]="Februar";
monthDE[2]="März";
monthDE[3]="April";
monthDE[4]="Mai";
monthDE[5]="Juni";
monthDE[6]="Juli";
monthDE[7]="August";
monthDE[8]="September";
monthDE[9]="Oktober";
monthDE[10]="November";
monthDE[11]="Dezember";
var monthEN = [];
monthEN[0]="January";
monthEN[1]="February";
monthEN[2]="March";
monthEN[3]="April";
monthEN[4]="May";
monthEN[5]="June";
monthEN[6]="July";
monthEN[7]="August";
monthEN[8]="September";
monthEN[9]="October";
monthEN[10]="November";
monthEN[11]="December";
var dayDE = [];
dayDE[0]="Montag";
dayDE[1]="Dienstag";
dayDE[2]="Mittwoch";
dayDE[3]="Donnerstag";
dayDE[4]="Freitag";
dayDE[5]="Sonnabend";
dayDE[6]="Sonntag";
var dayEN = [];
dayEN[0]="Monday";
dayEN[1]="Tuesday";
dayEN[2]="Wednesday";
dayEN[3]="Thursday";
dayEN[4]="Friday";
dayEN[5]="Saturday";
dayEN[6]="Sunday";
</script>

<script>
// replace month
$( "time.eventlist-datelabel-startdate" ).each(function() {
var label = $( this ).text();
// we now have "March 12"
var index = label.indexOf(" ");
var detectecMonth = label.substring(0, index);
var day = label.substring(index);
var translatedMonth = "";
for ( var i = 0; i < 12; i++ ) {
if (detectecMonth == monthEN[i]) {translatedMonth = monthDE[i]};
};
$( this ).replaceWith( "<time class='eventlist-datelabel-startdate'>" + day + ". " + translatedMonth + "</time>" );
});
// replace day-month
$( "time.event-meta-heading" ).each(function() {
var label = $( this ).text();
// we now have "Saturday, March 1, 2014"
var index1 =label.indexOf(",");
var detectedDay = label.substring(0, index1);
var indextemp = label.lastIndexOf(",");
var stringtemp = label.substring(index1, indextemp);
// we now have ", March 1"
indextemp = stringtemp.lastIndexOf(" ");
var detectedMonth = stringtemp.substring(2, indextemp);
// sometimes there are 2 blanks behind the month, therefore trim
detectedMonth = jQuery.trim(detectedMonth);
var day = stringtemp.substring(indextemp);
var indexyear = label.lastIndexOf(" ");
var year = label.substring(indexyear);
var translatedDay = "";
var translatedMonth = "";
for ( var i = 0; i < 12; i++ ) {
if (detectedMonth == monthEN[i]) {translatedMonth = monthDE[i]};
};
for ( var k = 0; k < 7; k++ ) {
if (detectedDay == dayEN[k]) {translatedDay = dayDE[k]};
};
$( this ).replaceWith( "<time class='event-meta-heading'>" + translatedDay + ", " + day + ". " + translatedMonth + year + "</time>" );
});
// translate "(map)"
$( "li[class='event-meta-item eventlist-meta-address']" ).each(function() {
$('body :not(textarea)').replaceText( "(map)", "(Karte)" );
});
</script>

#7 by Duarte Harris Cruz

15:04 on 21 May 2014

Hello.

I've tried this solution with mixed results.

What I have on the index did not change (the calendar & two "sumaries" from blogs).

The dates on the blog listings did work.

I'm using the Bedford template.

Do you have any idea why and/or ideas as to how to work around these issues?

Thanks in advance,

#8 by Duarte Harris Cruz

15:06 on 21 May 2014

Hello.

I've tried this solution with mixed results.

What I have on the index did not change (the calendar & two "sumaries" from blogs).

The dates on the blog listings did work.

I'm using the Bedford template.

Do you have any idea why and/or ideas as to how to work around these issues?

Thanks in advance,

#9 by ziska thalhammer

00:52 on 5 July 2014

I'm desperately trying to make this event calendar german.
https://trifonova-kindergarden.squarespace.com/event-calendar/?view=calendar&month=July-2014
Uwe, i tried your code, unfortunately it did nothing for me :(
I'm in developer mode.
thank you for ANY help!
ziska

#10 by dieter

19:25 on 23 September 2014

Hi David,

I try to design my website with squarespace but I can't change the words: add to cart, back to,... to dutch...
I can see you know haow to handle this ;-)
Can you help me a hand?

Best regards,

Dieter Coppens
Belgium

#11 by David Roessli

08:32 on 24 September 2014

Hi @Dieter,

It's a bummer that Squarespace doesn't provide an easy way to customise these labels yet… with all the sponsoring they are doing around the world, their product is still EN only.

The only way around for the time being is to inject JavaScript to replace specific character strings on the fly. Not ideal as it doesn't scale and can break when the template is updated…

Moreover, these replacements are template dependant.

You need to make an inventory of all the labels you need to translate, and then target a CSS class or ID for each of them before applying a similar approach to what is described above.

I can't really help more as I've given up on Squarespace for the time being. It turned out too much of a hassle to maintain all the different snippets of code…

#12 by David Roessli

08:57 on 24 September 2014

There is an online solution that can provide an easy way around:

https://localizejs.com/docs/integrations/squarespace

You can manage a glossary of word and phrases to translate on their site via your account.

Might be worth a try.

#13 by Anna Maria

09:19 on 16 January 2015

Resources like the one you mentioned here will be very useful to me! I will post a link to this page on my blog rental mobil . I am sure my visitors will find that very useful

#14 by Johnny Wu

04:52 on 29 January 2015

Hey David,

Thanks for giving us a shoutout in your breakdown of Squarespace 6 and their localization.

Anyone can feel free to email me directly if you have questions about the product, or integrating it into your site

johnny@localizejs.com

#15 by Kris

21:54 on 18 February 2015

Sadly, this does not work for the Switch template. Please let me know if anybody finds a workaround!

#16 by Cedric

11:42 on 6 April 2015

Hi,

Thank you for this very instructive post.

Please see below another way to localize dates (to French) for a summary calendar item. I inject this code in the local page injection section.

YUI().use("node", "datatype-date", "attribute", function(Y) {
// Setting the correct localization to French
Y.use("lang/datatype-date-format_fr-FR",
function(Y) {
Y.Intl.setLang("datatype-date-format", "fr-FR");
}
);

Y.on('domready', function () {
Y.all(".summary-metadata-item--date").each(function(i) {
// Select all the summary date items and initiate an each loop
// Adapt the selectors to your needs
var myContainer = this,
retrievedDate = this.getHTML(),
// Retrieves the date displayed by default in US format
parsedDate = Y.Date.parse(retrievedDate);
// Parse the retrieved date
Y.use("lang/datatype-date-format_fr-FR", function(Y) {
Y.Intl.setLang("datatype-date-format", "fr-FR");
// Switch the language ressource bundle to French
var formattedDate = Y.Date.format(parsedDate, {format:"%d %b %G"});
// Format the date with French standard
myContainer.setHTML(formattedDate);
// Output the formatted date
});
});
});
});

#17 by Laurent Sabbah

11:48 on 18 May 2015

Great post, but have you guys tried the easier way of localizing/translating Squarespace websites (including Squarespace 6 & Squarespace 7)?

Try https://www.bablic.com, We're getting amazing feedback from Squarespace users who are absolutely loving it since it's such an easy and user-friendly way to translate Squarespace sites.

Using Bablic.com you can choose any template you'd like, it works perfectly with all of them. Also lets you choose from machine translation or professional translation. It also lets you manually edit text, replace images and even edit css/style at the click of a button which makes sure your website keeps its look and feel in all of the languages you offer.

It also automatically ads a floating widget that lets you choose between your languages, for example French or English. You can also customize the widget if you'd like. Bablic also works on Mobile sites, I really recommend you give it a try.

Here's the tutorial for Squarespace integration which is extremely simple: http://blog.bablic.com/translate-your-squarespace-website-with-bablic/

Give it a try but just entering your website on our homepage at Bablic.com.

#18 by Cross

05:21 on 22 June 2015

We will help recreate your online image and give your site all of the abilities that it needs to attract new viewers and help to sell your business' products or services.


Melbourne SEO Services

#19 by Lindsay

23:41 on 24 June 2015

Hi David thank you so much for this excellent post!

I only have one problem... for some reason it's translating the date (the day number) to be one day before the actual date. See screenshot: https://www.dropbox.com/s/ifj8gev2xbus2c6/Screenshot%202015-06-21%2020.23.30.png?dl=0

Any idea why this might be happening? It might be worth mentioning that it flashes correctly in english for a millisecond... Any advice for a fix?

Thanks in advance for your time!

#20 by David

13:57 on 20 July 2015

Hi! You can also try https://poeditor.com/ for translating strings which is an online localization tool designed to make the localization process easier for both project managers and translators.

#21 by Lindsay

16:38 on 6 August 2015

Localize is amazing I can’t wait until they add date translations. Then I’d be set.

I tried poeditor and felt a little lost. This stuff is a little over my head so just being able to slap some code into the injector and only having to make minor changes like translating words is about as advanced as I can get.

Is there a way to add a day to the date? Right now it’s subtracting a day when translating :/

Here’s what I have currently injected into the footer:


/* List of months in Spanish */
var month = new Array(12);
month[0] = "enero";
month[1] = "febrero";
month[2] = "marzo";
month[3] = "abril";
month[4] = "mayo";
month[5] = "junio";
month[6] = "julio";
month[7] = "agosto";
month[8] = "septiembre";
month[9] = "octubre";
month[10]= "noviembre";
month[11]= "diciembre";

Y.use('node', 'node-load', function(Y) {
Y.on('domready', function() {

/* (1) Reformat blog entries published dates */
Y.all('time.published').each(
function() {
var pdate = new Date(this.getAttribute('datetime'));
this.setHTML(pdate.getDate () + " de "
+ month[pdate.getMonth()] + " "
+ pdate.getFullYear());
}
);
});
});

#22 by marcus

16:12 on 19 January 2017

Hey Guys, does anyone know how to change manually the buttons "backt to" and "prev / next" into the language i want? (German)

should be like "zurück zu" und "letzte / nächste"

Many thanks in advance.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)



Previous: Our short stay at the Hotel Eden in Chamonix

Next: Amazing Melody Gardot


About

Hello, my name is David Roessli. I am a freelance web designer and developer based in Geneva, Switzerland.

This weblog is an nth attempt to solve my multiple online personalities and weblog/rss feeds burnout issues. (more)

Words

I have been contemplating the idea of upgrading my desktop Mac since this spring. The latest 27" iMac (Quad-Core) seemed the perfect candidate, but the release of Apple's 27" Monitor last September made me stick with the Mac Pro...

Music

The autopsy of an iconic album cover picked up on Kottke.org. A stacked graph of successive radio signals from pulsar CP 1919, in a 1977 astronomy encyclopedia that originated in a 1970 Ph.D. thesis. Fascinating <3...

Pictures

Check out my latest Flickr ramblings. Mostly day to day cameraphone pictures stolen here and there.


© 2000-2016 David Roessli | v4.1 | as valid xhtml and css as possible | hosted by pair Networks | RSS feeds.