PageSourceSearch

https://meshtastic.org/assets/js/954b150c.6c4b18f4.js

js meshtastic.org collected 2026-09-24 08:46:07 UTC 9,345 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkmeshtastic=self.webpackChunkmeshtastic||[]).push([["27519"],{99592(e,t,n){n.r(t),n.d(t,{metadata:()=>i,default:()=>u,frontMatter:()=>a,contentTitle:()=>d,toc:()=>c,assets:()=>l});var i=JSON.parse('{"id":"development/firmware/oled-guide","title":"OLED Localization Guide","description":"Overview of Localization Steps","source":"@site/docs/development/firmware/oled-guide.mdx","sourceDirName":"development/firmware","slug":"/development/firmware/oled-guide","permalink":"/docs/development/firmware/oled-guide","draft":false,"unlisted":false,"editUrl":"https://github.com/meshtastic/meshtastic/edit/master/docs/development/firmware/oled-guide.mdx","tags":[],"version":"current","lastUpdatedBy":"rcarteraz","sidebarPosition":3,"frontMatter":{"id":"oled-guide","title":"OLED Localization Guide","sidebar_label":"OLED Localization","sidebar_position":3},"sidebar":"Sidebar","previous":{"title":"Building Firmware","permalink":"/docs/development/firmware/build"},"next":{"title":"Port Numbers","permalink":"/docs/development/firmware/portnum"}}'),o=n(91987),r=n(67008),s=n(87622);let a={id:"oled-guide",title:"OLED Localization Guide",sidebar_label:"OLED Localization",sidebar_position:3},d,l={},c=[{value:"Overview of Localization Steps",id:"overview-of-localization-steps",level:2},{value:"1. Create an Extended ASCII Custom Font",id:"1-create-an-extended-ascii-custom-font",level:3},{value:"2. Update the <code>customFontTableLookup</code> Function in <code>Screen.h</code>",id:"2-update-the-customfonttablelookup-function-in-screenh",level:3},{value:"3. Define Language and Font in <code>Screen.cpp</code>",id:"3-define-language-and-font-in-screencpp",level:3},{value:"4. Configure Language Settings",id:"4-configure-language-settings",level:3},{value:"Primary Method: Define in <code>variant/*/platformio.ini</code>",id:"primary-method-define-in-variantplatformioini",level:4},{value:"Alternative: Define in <code>userPrefs.h</code>",id:"alternative-define-in-userprefsh",level:4}];function h(e){let t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h2,{id:"overview-of-localization-steps",children:"Overview of Localization Steps"}),"\n",(0,o.jsxs)(t.p,{children:["This guide provides instructions for localizing an ",(0,o.jsx)(s.A,{term:"OLED",definition:"A display type used on many Meshtastic devices. The OLED Type setting selects which panel driver the firmware uses.",routePath:"/docs/terms/",children:"OLED"})," display by creating custom fonts, updating relevant code files, and defining language settings. The localization process involves the following steps:"]}),"\n",(0,o.jsx)(t.h3,{id:"1-create-an-extended-ascii-custom-font",children:"1. Create an Extended ASCII Custom Font"}),"\n",(0,o.jsxs)(t.p,{children:["Use a glyph editor to create a new font file. The easiest way is to use the online ",(0,o.jsx)(t.a,{href:"https://rawgit.com/ThingPulse/esp8266-oled-ssd1306/master/resources/glyphEditor.html",children:"glyph editor"})," from the ",(0,o.jsx)(s.A,{term:"OLED",definition:"A display type used on many Meshtastic devices. The OLED Type setting selects which panel driver the firmware uses.",routePath:"/docs/terms/",children:"OLED"})," library (",(0,o.jsx)(t.a,{href:"https://github.com/ThingPulse/esp8266-oled-ssd1306/tree/master/resources",children:"glyph editor source code"}),")."]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Copy and paste the existing font."}),"\n",(0,o.jsxs)(t.li,{children:["Modify it according to the desired codepage and save the new font file in the ",(0,o.jsx)(t.code,{children:"graphics/font"})," folder."]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.em,{children:"Note: The font file format differs from the common Adafruit GFX format."})}),"\n",(0,o.jsxs)(t.h3,{id:"2-update-the-customfonttablelookup-function-in-screenh",children:["2. Update the ",(0,o.jsx)(t.code,{children:"customFontTableLookup"})," Function in ",(0,o.jsx)(t.code,{children:"Screen.h"})]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsxs)(t.li,{children:["Map the double-byte UTF-8 code to the corresponding extended ASCII character of the desired codepage by updating the ",(0,o.jsx)(t.code,{children:"customFontTableLookup"})," function in the ",(0,o.jsx)(t.code,{children:"Screen.h"})," file."]}),"\n",(0,o.jsxs)(t.li,{children:["Modify the ",(0,o.jsx)(t.code,{children:"switch (last)"})," statement: Use the left byte from the UTF-8 code in the ",(0,o.jsx)(t.code,{children:"case"})," label to map the character's right byte to its extended ASCII code by specifying an offset."]}),"\n"]}),"\n",(0,o.jsxs)(t.h3,{id:"3-define-language-and-font-in-screencpp",children:["3. Define Language and Font in ",(0,o.jsx)(t.code,{children:"Screen.cpp"})]}),"\n",(0,o.jsx)(t.p,{children:"Add language-specific font definitions using conditional compilation:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-c",children:'#ifdef OLED_{LANG_NAME}\n#include "fonts/OLEDDisplayFonts{LANG_NAME}.h"\n#endif\n\n...\n\n#ifdef OLED_{LANG_NAME}\n#define FONT_SMALL ArialMT_Plain_10_{LANG_NAME}\n#else\n#define FONT_SMALL ArialMT_Plain_10\n#endif\n'})}),"\n",(0,o.jsx)(t.h3,{id:"4-configure-language-settings",children:"4. Configure Language Settings"}),"\n",(0,o.jsxs)(t.h4,{id:"primary-method-define-in-variantplatformioini",children:["Primary Method: Define in ",(0,o.jsx)(t.code,{children:"variant/*/platformio.ini"})]}),"\n",(0,o.jsxs)(t.p,{children:["Language settings can be defined in the ",(0,o.jsx)(t.code,{children:"platformio.ini"})," file under the appropriate variant directory:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-text",children:"build_flags =\n${esp32_base.build_flags}\n-D xxxxx\n-D OLED_{LANG_NAME}\n-I variants/xxxxx\n"})}),"\n",(0,o.jsxs)(t.h4,{id:"alternative-define-in-userprefsh",children:["Alternative: Define in ",(0,o.jsx)(t.code,{children:"userPrefs.h"})]}),"\n",(0,o.jsxs)(t.p,{children:["As an alternative to modifying ",(0,o.jsx)(t.code,{children:"platformio.ini"}),", the language can be defined in ",(0,o.jsx)(t.code,{children:"userPrefs.h"}),"."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-c",children:"#define OLED_{LANG_NAME}\n"})}),"\n",(0,o.jsx)(t.p,{children:"Both methods achieve the same result, and the choice depends on the specific project setup."})]})}function u(e={}){let{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},67008(e,t,n){n.d(t,{R:()=>s,x:()=>a});var i=n(71763);let o={},r=i.createContext(o);function s(e){let t=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(r.Provider,{value:t},e.children)}},87622(e,t,n){n.d(t,{A:()=>s});var i=n(71763),o=n(37773),r=n(91987);function s({term:e,definition:t,abbreviation:n,routePath:a="/glossary",children:d}){let[l,c]=(0,i.useState)(!1),[h,u]=(0,i.useState)(null),[p,f]=(0,i.useState)("top"),m=(0,i.useRef)(null),g=(0,i.useRef)(null),x=(0,i.useCallback)(()=>{let e;if(!m.current||!g.current)return;let t=m.current.getBoundingClientRect(),n=g.current.getBoundingClientRect(),i=window.innerWidth,o=window.innerHeight,r=document.querySelector(".navbar"),s=r?r.getBoundingClientRect().bottom:0,a=t.to
1p-s>=n.height+8,d=o-t.bottom>=n.height+8,l=a||!d?"top":"bottom";e="top"===l?t.top-n.height-8:t.bottom+8;let c=t.left+t.width/2-n.width/2;c=Math.max(8,Math.min(c,i-n.width-8)),f(l),u({top:Math.max(s+4,e),left:c})},[]);(0,i.useEffect)(()=>{let e;if(!l)return;let t=requestAnimationFrame(()=>{e=requestAnimationFrame(()=>{x()})}),n=()=>x(),i=()=>x();return window.addEventListener("scroll",n,!0),window.addEventListener("resize",i),()=>{cancelAnimationFrame(t),e&&cancelAnimationFrame(e),window.removeEventListener("scroll",n,!0),window.removeEventListener("resize",i)}},[l,x]);let v=(0,o.P_)("docusaurus-plugin-glossary"),L=(0,i.useMemo)(()=>{if(t&&"string"==typeof t&&t.length>0)return t;let n=(v&&v.terms||[]).find(t=>"string"==typeof t.term&&t.term.toLowerCase()===String(e).toLowerCase());return n&&n.definition?n.definition:void 0},[t,v,e]),j=(0,i.useMemo)(()=>{let t=n;if(!t){let n=(v&&v.terms||[]).find(t=>"string"==typeof t.term&&t.term.toLowerCase()===String(e).toLowerCase());t=n&&n.abbreviation}if("string"!=typeof t)return;let i=t.trim();if(i&&i.toLowerCase()!==String(e).toLowerCase())return i},[n,v,e]),w=(0,i.useMemo)(()=>a&&"string"==typeof a&&a.length>0?a:v&&v.routePath||"/glossary",[v,a]),y=d||e,b=e.toLowerCase().replace(/\s+/g,"-");return(0,r.jsxs)("span",{ref:m,className:"glossaryTermWrapper_ud7W",children:[(0,r.jsx)("a",{href:`${w}#${b}`,className:"glossaryTerm_x2nJ",onMouseEnter:()=>c(!0),onMouseLeave:()=>c(!1),onFocus:()=>c(!0),onBlur:()=>c(!1),"aria-describedby":`tooltip-${b}`,children:y}),L&&(0,r.jsxs)("span",{ref:g,id:`tooltip-${b}`,className:`tooltip_WjgA ${l?"tooltipVisible_AjfD":""} ${"top"===p?"tooltipTop_uMN4":"tooltipBottom_U9P5"} tooltipFloating_nLk7`,role:"tooltip",style:l&&h?{top:`${h.top}px`,left:`${h.left}px`}:void 0,children:[(0,r.jsx)("strong",{children:e}),j?` (${j}). `:"",L]})]})}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.