leforestier/yattag

Non ASCII characters

NT-me opened this issue · 8 comments

NT-me commented

How can i write text with "é", "è", "Δ" for example ?

Just write them like you just did here: "é", "è", "Δ".

For this to work:

  1. Your code editor must be instructed to save your Python source files as UTF-8 encoded text files
  2. Your Python source files must be UTF-8 encoded Python source files
  3. The XML or HTML document you're generating must be a UTF-8 encoded XML or HTML document

In most cases, you actually have nothing to do because this is the default.

1. Editor set up

This depends on your editor but usually code editors let you select the encoding when saving a file. Select UTF-8 if that is not already the encoding selected.

2. Source code

With python 3, the default encoding is already UTF-8: you have nothing to do
With python 2, you would add a

# -*- coding: utf-8 -*-

header at the top of your .py files

3. Document generated:

XML

The default encoding is UTF-8, you have nothing to do. If you want to be explicit, you can add an encoding attribute to the prolog:

<?xml version="1.0" encoding="UTF-8"?>

HTML5

The default encoding is also UTF-8, you have nothing to do. If you want to be explicit, you can add a

<meta charset="utf-8">

in your <head> section

HTML4

To declare an UTF-8 encoding, add

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

in your <head> section

I think this covers all cases.
Again, in most cases, you actually have nothing to do since UTF-8 is the default unless you're using Python 2, HTML4, or have set up your code editor incorrectly.

NT-me commented

The problem is only on windows.
I guess it don't use UTF-8.

Can you show some code and the error you're obtaining?

NT-me commented

For HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>QCM Stell - QCM</title>
    <link rel="icon" href="">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">
    <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
    <link rel="stylesheet" href="Uyolo.css">
    <script language="JavaScript">
function test(nom,n) {
  var rep=true;
  for (i=0; i<n; i++) {
   if (nom[i].value==1 && nom[i].checked==false) rep=false;
   if (nom[i].value==0 && nom[i].checked==true) rep=false;
  }
  return rep;
 }
</script>
    <script>function openCity(cityName, elmnt, color) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
   tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < tablinks.length; i++) {
     tablinks[i].style.backgroundColor = "";
}
document.getElementById(cityName).style.display = "block";
elmnt.style.backgroundColor = color;
}
document.getElementById("defaultOpen").click();</script>
  </head>
  <body>
    <div id="container" style="margin:1%">
      <img style="width:30%" src="https://media.discordapp.net/attachments/363315461087166466/551534610417319956/NUQxRjh6UDF2SEo0cFIwTEM1L3ZJdz09LS1sc09ZNXRaOWZLL0F3THk2aDRFM3lRPT0_--1dcac6de567f8b6d316709faf1516f.png" />
    </div>
    <div id="navbarMenuHeroA" class="navbar-menu" style="background-color: #80C18E;">
      <div class="navbar-end" style="background-color: #80C18E;">
        <a style="margin-right:10%; margin-left:10%" class="navbar-item is-active" href="index.html">
          <img src="home.svg" />
        </a>
      </div>
    </div>
    <section class="container" style="margin-top:1%">
      <nav class="breadcrumb">
        <ul>
          <li>
            <a href="../index.html">Home</a>
          </li>
          <li>
            <a href="UE.html">11</a>
            <li class="is-active">
              <a href="#">test</a>
            </li>
          </li>
        </ul>
      </nav>
    </section>
    <section class="content is-large">
      <h1 style="text-align:center">test</h1>
    </section>
    <section id="question" class="container">
      <hr />
      <form name="test">
        <div class="content is-medium">
          <p>
            <b>Question :</b>
          </p>
          <p>Pr�nom ?</p>
        </div>
        <br />
        <input type="checkbox" name="choix" value="1">Th�o</input>
        <br />
        <input type="checkbox" name="choix" value="0">Albert</input>
        <br />
        <br />
        <input type="button" name="bouton" value="check" onclick="if (test(choix,2)) {
alert('Bonne r�ponse.')
openCity('2', this, '#606c76')}
else {alert('Reponse fausse.')}"></input>
        <div id="2" class="tabcontent">
          <h1>Correction</h1>
          <p>1</p>
        </div>
      </form>
      <form name="test">
        <div class="content is-medium">
          <p>
            <b>Question :</b>
          </p>
          <p>1</p>
        </div>
        <br />
        <input type="checkbox" name="choix" value="1">1</input>
        <br />
        <br />
        <input type="button" name="bouton" value="check" onclick="if (test(choix,1)) {
alert('Bonne r�ponse.')
openCity('2', this, '#606c76')}
else {alert('Reponse fausse.')}"></input>
        <div id="2" class="tabcontent">
          <h1>Correction</h1>
          <p>1</p>
        </div>
      </form>
    </section>
    <section class="footer">
      <p style="text-align:center">Tout droit reserv� | Framework : bulma.io | G�n�r� par QCMaker</p>
      <a style="text-align:center" src="https://github.com/gnouf1/QCM-Maker">1.0.0</a>
    </section>
  </body>
</html>

For python:

# coding: utf-8
from yattag import Doc
from yattag import indent

version = ("1.0.0")

doc, tag, text = Doc().tagtext()


nom = input("Entrez le nom de ce QCM\n").encode('utf8')

UE = input("Veuillez saisir l'UE (uniquement la valeur numérique sans le point)\nExemple:\n      \"1.1 Psychologie, sociologie, anthropologie\" ==> 11:\n")
print(UE, "\n")

nbQ = input("\nCombien de questions souhaitez-vous mettre dans ce QCM ?\n")

doc.asis('<!DOCTYPE html>')
with tag('html', 'lang=\'fr\''):
    with tag('head'):
        doc.asis('<meta charset=\"utf-8\">')
        doc.asis('<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">')
        doc.asis('<title>QCM Stell - QCM</title>')
        doc.asis('<link rel="icon" href="">') #Modifier ici pour le favicon
        doc.asis('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">')
        doc.asis('<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>')
        doc.asis('<link rel="stylesheet" href="Uyolo.css">')
        with tag('script', language='JavaScript'):
            doc.asis("\nfunction test(nom,n) {\n  var rep=true;\n  for (i=0; i<n; i++) {\n   if (nom[i].value==1 && nom[i].checked==false) rep=false;\n   if (nom[i].value==0 && nom[i].checked==true) rep=false;\n  }\n  return rep;\n }\n")
        with tag('script'):
            doc.asis("function openCity(cityName, elmnt, color) {\nvar i, tabcontent, tablinks;\ntabcontent = document.getElementsByClassName(\"tabcontent\");\nfor (i = 0; i < tabcontent.length; i++) {\n   tabcontent[i].style.display = \"none\";\n}\ntablinks = document.getElementsByClassName(\"tablink\");\nfor (i = 0; i < tablinks.length; i++) {\n     tablinks[i].style.backgroundColor = \"\";\n}\ndocument.getElementById(cityName).style.display = \"block\";\nelmnt.style.backgroundColor = color;\n}\ndocument.getElementById(\"defaultOpen\").click();")


    with tag('body'):
        with tag('div', id='container', style='margin:1%'):
            doc.stag('img',style='width:30%', src='https://media.discordapp.net/attachments/363315461087166466/551534610417319956/NUQxRjh6UDF2SEo0cFIwTEM1L3ZJdz09LS1sc09ZNXRaOWZLL0F3THk2aDRFM3lRPT0_--1dcac6de567f8b6d316709faf1516f.png')

        with tag('div', id='navbarMenuHeroA', klass="navbar-menu", style="background-color: #80C18E;"):
            with tag('div', klass="navbar-end", style="background-color: #80C18E;"):
                with tag('a', style="margin-right:10%; margin-left:10%", klass="navbar-item is-active", href="index.html"):
                    doc.stag('img', src="home.svg")

# Fil d'Arianne
        with tag('section', klass='container', style='margin-top:1%'):
            with tag('nav', klass='breadcrumb'):
                with tag('ul'):
                    with tag('li'):
                        with tag('a', href="../index.html"):
                            text('Home')
                    with tag('li'):
                        with tag('a', href="UE.html"):
                            text(UE)
                        with tag('li', klass="is-active"):
                            with tag('a', href="#"):
                                text(nom)

# Titre
        with tag('section', klass='content is-large'):
            with tag('h1', style="text-align:center"):
                text(nom)

# Questionnaire
        with tag('section', id='question', klass="container"):
            doc.stag('hr')
            nbQ=int(nbQ)
            for j in range (0,nbQ):
                with tag('form', name=nom):
                    question = input("\n\n\nDonnez la question:\n")
                    with tag('div', klass='content is-medium'):
                        with tag('p'):
                            with tag('b'):
                                text("Question :")
                        with tag('p'):
                            text(question)
                    nbR = input("Combien de réponses possibles ?\n")
                    nbR=int(nbR)
                    for i in range (0,nbR):
                        reponse=input("\nProposez la réponse:\n")
                        v=input("est-elle une bonne réponse ? 1 -> oui | 0 -> non\n")
                        doc.stag('br')
                        with tag('input', type='checkbox', name='choix', value=v):
                            text(reponse)
                    nbRc=str(nbR)
                    jQ=str(j+1)
                    doc.stag('br')
                    doc.stag('br')
                    a=("if (test(choix,"+nbRc+")) {\nalert('Bonne réponse.')\nopenCity('"+jQ+"', this, '#606c76')}\nelse {alert('Reponse fausse.')}")
                    with tag('input', type="button", name="bouton", value="check", onclick=a):
                        text("")
                    with tag('div', id=jQ, klass="tabcontent"):
                        with tag('h1'):
                            text('Correction')
                        corr=input("Entrez la correction de la question:\n")
                        with tag('p'):
                            text(corr)

        with tag('section', klass='footer'):
            with tag('div', id="footer", style="text-align:center"):
                with tag('p'):
                    text("Tout droit reservé | Framework : bulma.io | Généré par QCMaker").encode('utf8')
                with tag('a', href="https://github.com/gnouf1/QCM-Maker"):
                    text(version)

result = indent(doc.getvalue())
print(result)
nom = UE + nom + ".html"
fichier = open(nom, "w")
fichier.write(result)
fichier.close()
input('Appuyez sur ENTREE pour quitter')

I can't test it in Windows right now, but here is what you should do to check where the problem comes from.
Run this instead of your script, and type the letter "é" when prompted for input:

s = ( 
"""<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>     
    <body>
    %s
    </body>
</html>"""
)

with open("test-litteral.html", "w") as fp:
    fp.write(s % "é")
    
with open("test-input.html", "w") as fp:
    fp.write(s % input())

Then check the two files you obtain in your web browser. Do they both fail to display the letter "é"? Or is it only the second file that fails?

NT-me commented

In both documents I have � :/

Note that it's not a problem related to yattag. It's a more general problem about encodings with Python on Windows.

Provided your web browser correctly interprets the HTML provided as a UTF-8 encoded document (which should be the case unless you've specifically instructed your browser to interpret every web page as latin1 or something), there must be a problem when writing the file.
It turns out that the open function in text mode uses a platform dependent encoding. I guess that must be the cause of your problem. Try the following:

s = ( 
"""<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>     
    <body>
    %s
    </body>
</html>"""
)

with open("test-litteral.html", "w", encoding = "utf-8") as fp:
    fp.write(s % "é")
    
with open("test-input.html", "w", encoding = "utf-8") as fp:
    fp.write(s % input())

Does that work? Or do you still have a problem with the second one?

NT-me commented

It's works !!

Thanks you !