In this meetup, we

  • Trained new translator by collective translation
  • Learned about roles and job description for each role
  • Learned about a code of conduct
  • Defined our responsibility assignment matrix
  • Defined our onboarding process for new contributors
  • Planned to experiment with translating in cross-checking mode
  • Updated our style guide and move it from old wiki page to GitHub and reformat it to Markdown
  • Planed about meetups and applying Mozilla products and projects in educations
  • Talked about how to improve Pontoon in the way that could help us work faster
  • Identified L10n related bugs, which crucial for Thai speakers

Wannaphong is our new translator. He works mainly on localizing Common Voice website. All Thai speakers in the meetup help him review his translations together at once, to demonstrate how to improve our translations.

We collectively reviewed the translations

Now our community has three roles, i.e., contributor, translator, and manager. In brief, everyone can translate at least by making a suggestion. A translator is supposed to work on reviewing other people's translation too. And a manager should manage to build a healthy community, and communicating between all participants.

Mozilla L10N is one of the most culturally diverse free/libre/open source software projects that coordinate contributors around the world for supporting their local languages. IMO, having a code of conduct, namely Mozilla Community Participation Guidelines is vital for making sure that the community does not discourage any demographic group of people from participating. Mozilla has simplified the Community Participation Guidelines, so it should be easier for us to practice.

We also defined our responsibility assignment matrix, and our onboarding process for new contributors, which is supposed to be published later.

For improving translation quality, we planned to experiment with translating in cross-checking mode on Common Voice project first because at least we have more than two translators working on this project. By having more than one translator, we can suggest the translation and another translator can cross-check by reviewing it. However, for trivial translations, cross-checking by making suggestion instead of translating in one step should be avoided.

We updated our style guide in Thai and put it on GitHub. To avoid editing to many suggested translations and make our translation consistent. The style guide is essential for anyone who wants to contribute.

We were updating the style guide, and defining the onboarding process

To have more participant and make more impact, we plan to invite people to talk about other topics rather than L10n in the meetup. We used to talk about Rust, and it went quite well.

About Pontoon, we agree that it is the best localization platform, which we have ever use. And it can improve even further by retrieving existing translations of terms in a long or short string that we about to translate. Moreover, enabling Pontoon to search only on Thai strings in particular patterns can detect errors, without looking at a translation unit one by one.

We believe that language features are critical for the competitiveness of Firefox and related projects among Thai language speaking users. So, we wish #1423593 and #425915 will get fixed soon.

  • Thank Opendream and @kengggg@twitter for offering the meetup venue for free.
  • Thank Wichai Termwuttipreecha for event planning.
  • Thank Peiying Mo, Delphine Lebédel, and @pompoko35@twitter, Teerapat Taechaiya for planning and organizing.
  • Thank Can Udomcharoenchaikit, Nattapong Ekudomsuk, Thanatip Sriviroonchai, Wannaphong Phatthiyaphaibun, Hassadee Pimsuwan, and Densin Roy. for contributing.

Almost everyone

Vee Satayamas

ผมสงสัยว่าทำไม laptop pc ที่เปิดตัวค.ศ. 2019 ยังใช้ Pentium N5000 ที่เปิดตัวตั้งแต่ค.ศ. 2017 อยู่

Pentium N5000 เปิดตัวค.ศ. 2017 TDP 6W ราคา 161 USD

Pentium 4417U เปิดตัวค.ศ. 2019 TDP 15W ราคา 161 USD

benchmark แบบ multicore แล้ว Pentium N5000 เร็วกว่า จาก spec ราคาเท่ากัน กินไฟน้อยกว่า ยี่ห้อเดียวกัน 🤣

ถ้าใช้ core เดียว Pentium 4417U ดีกว่า อีกอย่างคือใส่ RAM ได้ 32GB มากกว่า Pentium N5000 ที่ใส่ได้แค่ 8GB พอไปดู spec เครื่อง laptop ที่ทำมาขายกันก็ใส่ RAM มาแค่ 4GB ทั้งสองเบอร์

เดี๋ยวนี้ web browser ทำงาน multicore ได้แล้ว Rust compiler ก็ได้ PostgreSQL ก็ได้ โปรแกรมผมเองก็ยังทำได้เลย ก็คิดว่าการที่ยังใช้ N5000 อยู่มันสมเหตุสมผลมาก

  • ช่วงค.ศ. 1996 ผมคิดว่าน่าจะเปลี่ยนไปเขียน Java ได้แล้ว
  • ช่วงค.ศ. 2002 ผมคิดว่าน่าจะเปลี่ยนไปเขียน Ruby ได้แล้ว
  • ช่วงค.ศ. 2017 ผมคิดว่าน่าจะเปลี่ยนไปเขียน Clojure ได้แล้ว

ถ้ามองความเป็นไปในโลก Java กับ Ruby ในยุคที่ผ่านมาก็มีคนเอามาทำเว็บเยอะจริง ๆ เรื่อง Java นี่ใคร ๆ ก็เดาได้ ส่วน Ruby นี่กว่าคนจะใช้เยอะก็ช่วงค.ศ. 2006 แล้ว ผมก็แปลกใจนิดหน่อยว่าในที่สุดก็มีคนใช้เยอะจริง ๆ

ผมเขียนหลายภาษาที่ไม่ได้อยากเขียน ถึงจริง ๆ มันก็ดีนั่นล่ะ เช่น Logo Perl Python Prolog Pascal C C++ Awk JavaScript PHP xBase SQL SPARQL Rust พวกนี้เพราะว่าคนอื่นใช้ หลาย ๆ ภาษาผมก็ยังใช้อยู่ด้วย

ผมลองเขียนนิด ๆ หน่อยแต่ก็ไม่ได้ใช้อะไรจริงจัง ผมอาจจะจริงจังแต่มันไปไม่ถึง และไม่คิดว่าอยากจะเปลี่ยนไปใช้ เช่น Haskell OCaml Lua Erlang Kotlin Crystal Objective-C

ภาษาที่เข้า 2 กลุ่มนั้นไม่ได้คือ Go ซึ่งผมอยากเขียนเอง เคยใช้จริงจังแล้วแต่ก็เลิกไป Common Lisp และ Racket ก็เคยใช้จริงจังอยากเขียนเอง แต่คิดว่าเขียน Clojure แทนก็ได้

เป็นอันนึงที่เลือกนานมากคือสีวงลบของ Emacs ใช้ rainbow-delimiters 😅

 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "Noto Mono" :foundry "GOOG" :slant normal :weight normal :height 120 :width normal))))
 '(rainbow-delimiters-depth-2-face ((t (:inherit rainbow-delimiters-base-face :foreground "SeaGreen3"))))
 '(rainbow-delimiters-depth-3-face ((t (:inherit rainbow-delimiters-base-face :foreground "DeepPink1"))))
 '(rainbow-delimiters-depth-4-face ((t (:inherit rainbow-delimiters-base-face :foreground "SteelBlue1"))))
 '(rainbow-delimiters-depth-5-face ((t (:inherit rainbow-delimiters-base-face :foreground "orange red"))))
 '(rainbow-delimiters-depth-6-face ((t (:inherit rainbow-delimiters-base-face :foreground "DarkGoldenrod1")))))

AFAIK Generating UUID and Xid needs the MachineGuid, so I looked around how to obtain it.

And this is the solution, which I'm not sure if it will work on every Windows machine. 😅

use winreg::RegKey;
use winreg::enums::*;
use std::io;

fn main() -> io::Result<()> {
    let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
    let cur_ver = hklm.open_subkey("SOFTWARE\\Microsoft\\Cryptography")?;
    let guid: String = cur_ver.get_value("MachineGuid")?;
    println!("MachineGuid = {}", guid);


name = "mach_guid"
version = "0.1.0"
authors = ["veer6"]
edition = "2018"

winreg = "0.6"

เอกสารเดี๋ยวนี้อาจจะไม่ได้มาแบบเป็นเล่ม ๆ อย่างเดียว บางคนอาจจะใช้ E-book reading จอ 6 นิ้วอ่าน บางคนอาจจะ print ใส่กระดาษ A4 บางคนอาจจะอ่านใน Tablet บางคนอาจจะอ่านบนจอใหญ่ บางคนอาจจะอ่านในโทรศัพท์มือถือ

มันคงไม่ค่อยดีเท่าไหร่ที่จะต้องมาจัดหน้าให้ทุกแบบเอง คนที่เขียนเนื้อหาก็ควรจะเขียนเนื้อหาไป ไม่ต้องมากังวลกับการจัดหน้ามาก

MS Word มันกึ่ง ๆ ระหว่างจะเน้นเนื้อหา หรือว่าจะเน้นจัดหน้าดี จะเลือกว่าส่วนไหนเป็น heading ก็ได้ แต่นึกอยากจะกำหนด font กำหนดขนาดตัวอักษรของแต่ส่วนเองก็ได้อีก

จะใช้ Word แบบเน้นเนื้อหาก็ได้ โดยการเลือก style แทนที่จะไปจัดเอง แต่พอทำจริง ๆ ส่วนมากออกมา format ไม่เป๊ะ มันมีวิธีหลายแบบที่จะทำให้เอกสารออกมาหน้าตาคล้าย ๆ กัน มอง style ก็ไม่ค่อยจะเห็นชัดเท่าไหร่ ทีนี้เอามาประมวลผล หรือแค่จัดรูปแบบใหม่ให้เหมาะกับ online หรือแม้กระทั่ง ebook reader จอเล็ก ๆ มันจะเละ

มันมีสิ่งที่คิดมาแก้เรื่องนี้หลายตัวเช่น GNU Texinfo มันก็ใช้ได้เอกสารของ GNU Project ทั้งหมดใช้ตัว Texinfo เวลาดูเว็บของ GNU หน้าตามันจะซ้ำ ๆ เบื่อ ๆ หน่อย แต่ก็เป็นวิธีที่ทำเอกสารที่ทำทีเดียว ออกมาได้ทั้ง HTML, Info, man ทำเป็น PDF ก็ได้ ปัญหาของ Texinfo คือกว่าจะเขียนเป็นมันก็ไม่ได้ยาก แต่ก็ยากกว่า Word

อีกตัวคือ Gitbook อันนี้ใช้เขียนหนังสือเป็นเล่ม ๆ ได้เลย แล้วก็เอามาสร้างได้หลาย format คล้าย ๆ กับ GNU Texinfo แต่ว่าใช้ Markdown คนทาง IT เดี๋ยวนี้หลาย ๆ คนก็เขียน Markdown เป็นเลย เป็น format ที่ดูง่ายมาก ๆ บางคนอาจจะบอกว่าเปิด docx ออกมาอ่าน format ข้างในก็ได้เหมือนกัน แต่มันก็อ่านยากกว่า Markdown มาก ๆ แต่ถึง Markdown จะง่ายอย่างไรมันก็ยากกว่าใช้ Word อยู่ดี Gitbook ในเว็บเขามีตัวแก้เอกสารแบบ WYSIWYG มาให้เลย แต่ format มันก็จะเป๊ะอยู่ดี WYSIWYG ของเขาไม่ใช่แบบที่ให้มาเลือก font จัดโน่นจัดนี่เอง แต่พอเป็นตัวหนังสือก็จะเลือกได้ว่าจะเป็น Heading 1, Heading 2, Heading 3 อะไรทำนองนั้นไป

ผมมองว่าแบบ Gitbook นี่ล่ะที่น่าจะเหมาะเพราะ

  1. แยกกันระหว่างเนื้อหาและการจัดหน้า
  2. แก้ไขแบบเห็นเหมือนจริง (WYSIWYG) ได้เลย ทำให้ง่าย
  3. ตรวจ format ง่าย เพราะว่าถึงจะเปิดแบบ Markdown มาก็พอจะอ่านรู้เรื่องเลย ทำให้รู้ว่ามันเก็บอะไรลงไปกันแน่
  4. อีกข้อหนึ่งที่แถมคือเวลาแก้ไขเอกสารด้วยกันหลาย ๆ คนพร้อมกันผ่านเว็บนี่มันสะดวกกว่าการส่งไฟล์กันไปมาเยอะแยะ

ผมว่าเทคโนโลยีมันพร้อมแล้ว เหลือแต่ว่าคนจะอยากเปลี่ยนเมื่อไหร่

update 2019-08-04

ยกตัวอย่างเพิ่มเติมเพื่อให้เห็นภาพว่า markdown มันเพิ่มเพิ่มขนาด font ตรง ๆ ไม่ได้ ต้องไปทำผ่านการสร้าง header ทำให้เวลาเอาไปใช้ไม่ต้องมีตีความว่า TH Sarabun PSK 24 นี่มันคืออะไร เป็น header หรือเปล่า หรือ header ระดับไหน

สมัยที่เรียนหนังสือเขามักจะเอา Fibonacci number มาเป็นตัวอย่างกัน function ก็เป็นงี้ครับ

fib(0) = 0 fib(1) = 1 fib(n) = fib(n-1) + fib(n-2) สำหรับ n มากกว่า 1

ซึ่งเอามาแปลงเป็น Clojure ได้แบบตรงไปตรงมาเลย

(def fib
  (fn [n]
    (if (<= n 1) n
        (+ (fib (- n 1)) (fib (- n 2))))))

ผมลองรันบนเครื่องผมใช้เวลา 4.324 วินาที ซึ่งมันช้าเพราะไปเรียก fib ซ้ำไปซ้ำมา ดูง่าย ๆ fib(4) ก็ไปเรียก fib(3), fib(2) แล้ว fib(3) ก็ไปเรียก fib(2) อีกซ้ำ พอเลขมากก็ซ้ำไปเรื่อย ๆ

จริง ๆ มันมีวิธีหล่อ ๆ เยอะแยะที่จะแก้ปัญหานี้ให้เร็วขึ้น แต่ถ้าเราไม่ต้องหล่อมาแก้แบบดอกเดียวเสร็จก็ใช้ memoize เขียนแบบนี้

(def fib
   (fn [n]
     (if (<= n 1) n
         (+ (fib (- n 1))
            (fib (- n 2)))))))
(println (time (fib 42)))

แก้นิดเดียวเอา memoize มาครอบ function ไว้ มันจะจำ function ที่เคยเรียกไว้แล้วส่งผลกลับมาเลยโดยไม่ต้องไล่ยาว ผลคือโปรแกรมใช้เวลารันเหลือ 0.820 วินาที

จริง ๆ มันจบแล้วล่ะ แต่เขียนให้ดูอีก function แบบใช้ loop

(defn fib [n]
  (loop [i 1 acc0 0 acc1 1]
    (if (< i n)
      (recur (inc i) acc1 (+ acc0 acc1))
(println (time (fib 42)))

อันนี้ใช้เวลาแค่ 0.0976 วินาที แต่ก็จะเห็นได้ว่าโปรแกรมเปลี่ยนไปเยอะ เปลี่ยนวิธีคิดเยอะ memoize นี่มันแทบไม่ต้องคิดต้องเขียนอะไรมากเลย ใส่ไปแล้วได้ผลเลย

ขอบคุณ ที่แนะนำ function time มาครับ

ผมมักจะไปสร้าง script ด้วย Python สั้น ๆ ไว้ใน $HOME/bin หรือ /usr/local/bin ก็ได้ แล้วก็ chmod 755 <ชื่อไฟล์> แล้วก็จะได้เรียกจาก shell ได้เลย

ผมเขียนไว้ 3 ตัวตามนี้


#!/usr/bin/env python
# * mode: python-mode *

import deepcut
import json
import sys

for line in sys.stdin:
    line = line.strip()


#!/usr/bin/env python
# * mode: python-mode *

from pythainlp.tokenize import word_tokenize

import json
import sys

for line in sys.stdin:
    line = line.strip()
    print(json.dumps(word_tokenize(line ,engine='newmm')))


#!/usr/bin/env python
# * mode: python-mode *

from wordcut import Wordcut
import json
import sys

wordcut = Wordcut.bigthai()

for line in sys.stdin:
    line = line.strip()


ใน shell จะเรียกเดี่ยว ๆ ก็ได้แบบ

$ newmm < file1.txt > file1.ndjson

แต่ส่วนมากก็จะเรียกผ่าน for-loop เถื่อน ๆ แบบนี้

$ for x in *.txt; do newmm < $x > $x.ndjson; done



#!/usr/bin/env ruby
# * mode: ruby-mode *

require "json"
require "csv"

h =
while gets
    .each{|w| h[w.chomp] += 1}
h.to_a.each{|row| puts CSV::generate_line(row)}

เวลาเรียกก็ไป pipe แบบนี้เลย

cat file1.txt | newmm | wcnt

เดี๋ยวนี้คนดี ๆ เขาคงใช้ Jupyter กันหมดแล้ว ผมก็พยายามฝึกอยู่เหมือนกัน แต่ยังไม่คล่อง บางทีก็เลยเอาแบบนี้ไปก่อน

I failed to download a list of PDFs by Wget, cURL, and Slimerjs. So I used Firefox and shell script.

First, I disable Pdfjs to force Firefox to download PDFs.

I wrote a shell script for opening a URL with PDF file, and then I use xdotool to close the Firefox window. For xdotool command, thank Jon G – Megaphone Tech for his comment at Unix Exchange.


for url in `sort -u eng_pdf_urls.txt | grep -i pdf`
    echo $url
    firefox -P exp1 "$url" &
    sleep 10
    echo CLOSE
    xdotool search "Mozilla Firefox" windowactivate --sync key --window 0 --clearmodifiers alt+F4
    sleep 10

I didn't use headless because I don't know how to close it properly. I tried timeout command but Firefox detected it as an improper shutdown.

I ported my program for showing concurrency from Erlang to Elixir. I guess this is still not Idiomatic Elixir. 😅

defmodule Con1 do
  def log(p, i) when rem(i, 3000) == 0 do
    IO.puts "#{p} #{i}"
  def log(_, _) do

  def cnt(_, 0) do
  def cnt(p, i) do
    log(p, i)
    cnt(p, i - 1)

  def par_cnt(0) do
  def par_cnt(n) do
    spawn fn() -> cnt(n, 3000000) end
    par_cnt(n - 1)