MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    1. Home
    2. MMRIZE
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.
    M
    Offline
    • Profile
    • Following 0
    • Followers 8
    • Topics 29
    • Posts 952
    • Groups 0

    MMRIZE

    @MMRIZE

    162
    Reputation
    379
    Profile views
    952
    Posts
    8
    Followers
    0
    Following
    Joined
    Last Online

    MMRIZE Unfollow Follow

    Best posts made by MMRIZE

    • MMM-Planetarium

      MMM-Planetarium

      MagicMirror Module to display constellations, stars, galaxy, … using VirtualSky Library

      Screenshot

      screenshot

      • various configurable options.
      • real-time live update
      • animated auto-panning.
      • mouse/keyboard/touch support

      https://github.com/MMRIZE/MMM-Planetarium

      posted in Education
      M
      MMRIZE
    • MMM-Scenes

      MMM-Scenes

      “Life is a theatre set in which there are but few practicable entrances.”
      ― Victor Hugo, Les Misérables

      MagicMirror module to change screen scenes by time and order with ANIMATION EFFECT.

      Demo

      MMM-Scenes Demo
      Click To Play

      Concept

      The scenario of the MM screen is made up of a series of scenes. Each module has its role in its appearance scenes to enter and exit by design.

      When a scene begins, all modules whose roles end, will be expelled, and all modules that have the parts in that scene will be admitted.

      As described in the scenario, your MM screen will play a drama with modules.

      Features

      • control show/hide modules by assigning scene names into the module’s class
      • custom animations for modules expel/admit
      • control scenes by notification and WebURL endpoints.
      • Loop control
      • custom indicators

      Warning

      Old/weak SBCs (e.g. RPI 3 or older) may not have enough power to handle severe animations.

      More Details
      https://github.com/MMRIZE/MMM-Scenes

      posted in System
      M
      MMRIZE
    • [HOW_TO] MagicMirror as Desktop Wallpaper (all platform : updated)

      Since MM 2.17 (2021-10-01), You can use your MM as Desktop wallpaper (like Rainmeter of window). Easy.

      Environment

      • MagicMirror >= 2.17

      For MacOS / Linux

      image

      configuration

      // in your config.js add these lines.
      // (ADDED 2024-05-16) These lines should be placed inside of `config`, not end of file.
      // I forgot to mention it because it seemed so obvious. Surprisingly, it seems to be misunderstood as appending these to the end of the file.
      
      
      electronOptions: {
      	width: 1920,
      	height: 1200,
      	fullscreen:  false,
      	backgroundColor: '#00000000',
      	titleBarStyle: 'none',
      	frame: false,
      	type: 'desktop',
      	hasShadow: false,
      	transparent: true,
      	resizable:   false,
      },
      electronSwitches: ["enable-transparent-visuals"],
      
      

      That’s all.

      For Windows 10

      image

      Requirements

      • You might not have python > 3.7 and node-gyp(It requires Visual Studio Tools to install).
      • So, Read this link and setup your environment. (Install Visual Studio things and python)

      Install

      Unlike Mac/Linux, for Windows, you need some hacks for preparation.

      cd ~/MagicMirror # Your magicmirror directory
      npm install --save electron-wallpaper-napi
      # If fails, you might hava some issues about Visual Studio things. Read above;
      

      Then, open js/electron.js with your editor, and add these two lines;

      //around line 7
      ...
      const electron = require("electron");
      const core = require("./app.js");
      const Log = require("logger");
      
      const electronWallpaper = require('electron-wallpaper-napi')  // <-- Insert
      
      // Config
      let config = process.env.config ? JSON.parse(process.env.config) : {};
      ...
      

      and

      // around line 50
      ...
      // Create the browser window.
      mainWindow = new BrowserWindow(electronOptions);
      electronWallpaper.attachWindow(mainWindow)  // <-- Insert
      ...
      

      Configuration

      // in your config.js add these lines.
      
      electronOptions: {
      	//width: 1920,
      	//height: 1080,
      	//x: 0,
      	//y: 0,
      	fullscreen:  true,
      	backgroundColor: '#00000000',
      	frame: false,
      	type: 'desktop',
      	transparent: true,
      },
      electronSwitches: ["enable-transparent-visuals"],
        
      

      CSS

      :root {
        --color-text: #DDD;
        --color-text-dimmed: #BBB;
        --color-text-bright: #fff;
        --color-background: rgba(0, 0, 0, 0);
       /* make fonts color brighter */
      
        --font-size: 2vh;
        --font-size-small: 0.75rem;
      
        --gap-body-top: 20px;
        --gap-body-right: 120px;
        --gap-body-bottom: 20px;
        --gap-body-left: 40px;
      /* adjust margin for your screen */
      }
      
      * {
        text-shadow: 2px 2px 5px #000000; /* make text more readable on the background image */
      }
      
      
      

      replace or add this to contents of your custom.css

      posted in Tutorials
      M
      MMRIZE
    • Long time no see and need a help.

      It’s truly been a long time.

      At the beginning of this year, I wrapped up 13 years of business in Frankfurt, Germany, and returned to Seoul, Korea. Due to the move and various other matters, I haven’t been able to focus on this project. However, since February, I’ve started working again—this time in Beijing, China.

      One serious issue is that, for various security-related reasons, it has become extremely difficult to access GitHub, this project, and the community. As you may know, China’s Golden Shield censorship system and the Great Firewall have rendered almost all VPNS useless. It’s not just GitHub—accessing Google, Dropbox, or any external APIS has become very challenging. On top of that, my company’s security policies prevent me from working on external projects during work hours. (and even in my free time… What a situation!)

      As a result, I haven’t been able to maintain many of the MagicMirror modules I developed, let alone respond to GitHub issues.

      Given these circumstances, maintaining my GitHub repositories is extremely difficult.
      If anyone is interested in any of my modules, I would be happy to give them repository management rights. I had a similar absence from this scene in the past, and back then I regrettably transferred full ownership of some modules—which I now deeply regret. This time, I intend to assign co-maintainer rights instead. If you’re interested, please email me (eouia0819@gmail.com). I may have difficulty checking emails, but I’ll try to do so as much as I can.

      I’m not sure when my work in China will end, but I want to express that I still care deeply about this community.

      posted in Forum
      M
      MMRIZE
    • MMM-LogExt

      MMM-LogExt

      Log Extension module for MagicMirror

      screenshot

      Concept

      Many beginners have a problem tracing an unexpected issue when they run the MagicMirror.
      Usually, the start of debugging would be to examine backend-log and frontend-log but people may have confusing to use both how to.

      I know there already exists MMM-Logging to help with this issue, but it seems not maintained anymore, and I need more features, so I have to re-invent a wheel by myself.

      Features

      • To deliver frontend log (used by MM’s Log Object) to backend log
      • Customizable/Decorative Log messages
      • To monitor Notifications
      • window.error and unhandledRejection would be caught then be transmitted to the backend
      • To be able to log external messages from other programs or devices via HTTP request

      IMPORTANT : This module deliver only Log.xxx() to the backend, not console.xxx().

      https://github.com/MMRIZE/MMM-LogExt

      posted in System
      M
      MMRIZE
    • MMM-CalendarExt3

      MMM-CalendarExt3

      New MagicMirror module for calendar view. (successor of MMM-CalendarExt2)

      Screenshot

      screenshot

      Concept

      My previous module, MMM-CalendarExt2, was always notorious for its difficulty to use. I need a more easy and light one. So I rewrite this from scratch newly.

      Features

      What’s different with CX2.

      • Only focusing on how it shows; Parsing is delegated to original MagicMirror module calendar. (It means the calendar module is REQUIRED to use this module.)
      • Only week and month views. I found that people are rarely interested in other views on CX2. So I drop out different views.
      • Respect to original MM’s hide/show mechanism. Now you can hide/show this module easily with other scheduler or control modules. (By the way, Look at this module also. - MMM-Scenes)
      • No dependency on the 3rd party modules (e.g. momentJS or Luxon, etc.). This is built with pure JS and CSS only.

      Main Features

      • week view or month view
      • locale-aware calendar
      • customizing events: filtering, sorting, transforming
      • multi-instance available. You don’t need to copy and rename the module. Just add one more configuration in your config.js.

      DETAILS : https://github.com/MMRIZE/MMM-CalendarExt3

      posted in Utilities
      M
      MMRIZE
    • RE: MMM-CalendarExt3 Resize module

      @Xsoldier2000
      This module usually (and for your convenience), uses the whole width of the region that this module lays on. So, if you want to use 3/4 width of the entire screen, it will be easier to limit the width and location of the region itself. So, if you want to lay this module into top_center, guess how to expand and locate top_center region to 3/4 width from the right edge. (There could be many solution and condition, so I cannot point a silver bullet.)

      posted in Custom CSS
      M
      MMRIZE
    • [HowTo] Update MM/Modules safely.

      1. Please don’t do it.

      If your current MM is working without issue, and you don’t really need any new features of the updated version, Don’t update. If the new version still cannot solve your current issue explicitly, Don’t update.
      Leave it as it is still being working. Dare to say again, Don’t update

      Nevertheless, if you still want to update,

      2. Prepare the backup

      Backup your config/config.js and css/custom.css files into somewhere safe.
      And you might probably have some additional module-specific resources, like credential JSON, DotEnv(.env) files, or some data feeds/files. Backup them also.

      3. Check your OS.

      A timeworn OS might need additional or newer dependencies for new MM/modules features.
      So you might need to update your OS first. Especially Raspbian or any linux-based OS for SBC, just reinstall from scratch with formatting SD(or MMC). For windows/MacOS, It is less important, so you can ignore this.

      If you feel that a fresh reinstall might look somehow too much, at least an update to a recent version might be needed.

      4. Check your environment.

      NodeJS version and NPM version should be matched with MM’s requirement. Usually, requirements for electron would be those. (I recommend NVM to you to manage versions of NodeJS)
      Some specific native-node-module which needs rebuild (electron-rebuild or node-gyp or something similar) would be affected by these version differences.

      5. new instance in another directory, if possible.

      Ok, You are a dotard so will not format your RPI, and will not update your environment at all. It is up to you.
      If so, at least you’d better install a new MM/modules in another directory, not update the current MM/modules directly.

      You can rename the current directory as an insurance. You can restore yours again at any time when you fail with a new version.

      6. Installation is better/easier than Updating, always.

      Trust me. Installation is easier than updating.

      1. Most module developers are describing well how to install but not how to update. (including me. sorry.) You probably already have experience with installation, just do it once again.
      2. The issues from different versioned dependencies would make all things messed up. A new installation could avoid many cases of them.

      7. Remove updateNotification module.

      Sometimes, not knowing is the solution. Avoid update obsession.

      Good luck!

      posted in Tutorials
      M
      MMRIZE
    • RE: MMM-Touch or similar without visible module

      @mmmmh
      useDisplay: false,

      posted in Troubleshooting
      M
      MMRIZE
    • [Proposal] Enhanced Translator

      :::
      This is not a request but rather a proposal.
      Recently, I rewrote Translator for my purpose, but if someone has interests, I’ll make a PR to the original repository to share.
      Anyway, I need some help; test, proof of concept.

      I’m just afraid that I was the only one who needs this. :)

      I apologise in advance for a too-long article to read.
      :::

      MagicMirror² Enhanced Translator

      This project is rewriting the global Translator object of MagicMirror to have enhanced features.

      • dev repository : https://github.com/MMRIZE/MagicMirror_EnhancedTranslator
      • dev branch : https://github.com/MMRIZE/MagicMirror_EnhancedTranslator/tree/enhanced-translator (original based 2.16-develop of MicMich/MagicMirror)
      • demo branch(here) : https://github.com/MMRIZE/MagicMirror_EnhancedTranslator/tree/master

      Motivation

      For several years, the current translator class works for L10N/I18N of MM successfully. But there is still some lack of features. Especially in the below cases, we need more improvements.

      • Maintenance of translation files.

        Whenever a new translation by the user is added or updated, translations.js(core) or .getTranslations()(module) should be updated and released officially to prevent the update-conflicts issue.

        By versioning up, some old translation might be obsoleted or needs to be updated for the change of terms used in MM.

        And also, it is hard to add a light-modified custom dictionary like de-au.json. It would probably be copied from the original de.json, and even though the difference might be very little, but entire de-au.json should be published and maintained.

      • Locale-aware

        One xx.json cannot hold several locale-specific translations difference. US English and Australian English are noticeably different from each other from vocabulary to grammar. Some Australian users may prefer "G’day mate" instead of "Hello". Some British people might not be comfortable with the spelling of "Color".

        English users in Canada(en-CA) notate dates as 4 September 2021 or September 4, 2021, And French in Canada(fr-CA) notate date as 4 septembre 2021. and the usual numeric format is 2021-09-04. But in the US(en-US), people genrally use 09/04/2021. And in France(fr-FR) it is 04/09/21.

        German people prefer to write a number like 1.234.567,89, but in US, it will be 1,234,567.89. In India, it will be 12,34,567.89. In China, under ‘hanidec’ numbering format, it will be 一,二三四,五六七.八九.

        Generally, MM module developers have tried to solve these issues by providing specific additional L10N converting by config. But occasionally it makes another too-many-config-value issue.

        And for the date format, we are facing momentJS deprecation. (Well, luxon might be the excellent alternative, though.)

      • For multi-lingual user (too-simple-fallback)

        Current fallback mechanism - primary language or ‘en’ is not enough. Some people use multi-languages in their country.

        Certain Serbian users can speak Serbian, Croatian, Romanian, Hungarian, Slovak, Czech, etc. Anyway English might not be his prefer language. With luck, some modules might provide hu.json. and some modules might provide hr.json. But he should select only one language for his Mirror. And whatever he chooses, other modules will display English. Of course, en must be the last-final-safe fallback. However, it will be convenient and user-friendly if MM provided more steps before the final solution.

        Also, there could be cases like this; sometimes fr-CA user needs fr-CA translation at first, then want to use familiar fr, then en-CA if available, at last reluctantly use standard en as final fallback.

      • flexibility for natural language process

        translator is not a template engine. However, if it could handle Object and Array it would provide more abundant natural translation results. In some counties, the first name is preferred to Family name, and in some countries, vice versa. If translator can handle user: {firstName, familyName, gender, title} together instead of addressing each userFirstName, userFamilyName, userGender, userTitle, it could reduce the codes and make meaningful context.

        Customizable value-formatters would be a help for L10N/I18N also. A Module developer needs to support only general value and format, and then a translation provider could convert that value to another format with those formatter on dictionaries.

        For example; Instead of "Unread mail: 3", more natural sentences "There is a mail unread.", "There are 3 mails unread." or "Es gibt eine ungelesene Mail.", "Es sind 3 Mails ungelesen" could be possible with some formatters and language/locale information by translation provider, not by module developer himself.

        Finally, translation could be used as a light template engine with those features. It will give more freedom to the user who wants to customize the MM.

      Those are the main reason what this project begins.

      Improvements

      • Multi-language fallback by prefer order and related-locales
      • Translation dictionaries autoload
      • Handling Object and Array as replacement variables
      • custom value formatting

      Usage

      config and fallback order

      // in `config.js`
      language: "fr-CH",
      languages: ["it", "de-CH"],
      locale: "fr-CH",
      
      • config.languages are proposed. You can define multi-languages to use by preferred order.

      • For backward compatibility, config.language would still be used. config.language will be regarded as a primary language. In above example, this configuration is same with languages: ["fr-CH", "it", "de-CH"]. (translator itself doesn’t refer config.language but other modules might be using it.)

      • For convenience, config.languages: "it, de-CH" would also be allowed.

      • "en-CA" or "en-ca" would be suitable for language code. But don’t use "en_CA". Ithe t is not standard BCP-47 format.

      • Each locale-like language code implies to refer its ancestor dictionaries. "fr-CH" will use fr-ch.json and fr.json. When translator cannot find the term in the fr-ch.json, it will try to seek from fr.json. Another case; zh-Hans-HK will try zh-hans-hk.json then zh-hans.json, then zh.json (and finally en.json, of course). But zh-hant.json or zh-tw.json will not be referred.

      • So, in the above case, the translator will refer to dictionaries by order - fr-ch, fr, it, de-ch, de and the final implied fallback en.

      • If the translator cannot find any term or dictionary in module’s /translations, it will try MM’s /translations(core). If nothing is matched in the end, null or runtime fallback message(from .translate()) would be returned.

      • So you can extend your sub-dictionary easily. If you already have a complete dictionary - de.json, you can make de-au.json without copying whole terms. Just describe exclusive terms only being different with de.json. All other unmentioned terms in de-au.json will be referred from de.json automatically.

      • locale would be needed. If not described, default would be used in translator, and it would generally infer your default system locale.

      translation file and syntax

      • For backward compatibility; same naming rule with current lower capitalized BCP-47 format. (e.g. en.json, en-ca.json)

        By the way, current MM’s translations files are not fully fitted for BCP-47. kr.json should be ko.json, etc…

      • For developer; You don’t need to maintain translations.js or .getTranslations(). Needed translation files that exist in /translations directory will be loaded automatically by the user’s configuration.

      • For backward compatibility; same syntax with current - "TERMS" : "DEFINITION" is still used. (e.g. { "SAY_HELLO" : "Hello, {userName}!" })

      • (new) Nested Object/Array index is usable. (e.g. { "SAY_HELLO" : "Hello, {user.0.name} and {user.1.name}!" })

      • (new) pre-defined or custom formatter is usable. Formatter symbol is @. (e.g. { "TIME_INSTANT" : "It's {now@myTime}" }). Variable now will be converted to specific format by definition of @myTime formatter defined in translation dictionary.

      • (new) Definition of formatter could be added. Translation file provider can adjust options to format the variable replacements for his language/locale.

      • Drawback; Dynamic loading translation files on runtime could spit out dev-console 404 error messages, because translator doesn’t know that every translations exist or not. Error messages make no harm and they are ignorable, but annoying anyway.

      Example

      // in MM-Something module
      var translated = this.translate("TIME_INSTANT", { now: new Date() });
      // => It's Monday, 9 in the morning.
      
      /* modules/MM-Something/translations/en.json */
      {
        "SAY_HELLO": "Hello, {user.name}!",
        "TIME_INSTANT": "It's {now@myTime}.",
      
        "@myTime": {
          "format": "DateTimeFormat",
          "options": { "dayPeriod": "short", "hour12": true, "weekday": "long", "hour": "numeric" }
        }
      }
      
      /* modules/MM-Something/translations/de.json */
      {
        "SAY_HELLO": "Hallo, {user.name}!",
        "TIME_INSTANT": "Es ist {now@myTime}.",
      
        "@myTime": {
          "format": "DateTimeFormat",
          "options": { "dateStyle": "long", "timeStyle": "short" }
        }
      }
      

      With locale = "en-US" and language = "en", translated result will be It's Monday, 9 at night.

      With locale = "de-DE" and language = "de", translated result will be Es ist 6. September 2021 um 21:09.

      As it shows, module developer doesn’t need to preserve every available conversion result. Translator maker could format it by himself for his locale and language.

      Translator spec.

      (module).translate(key [, variablesObject][, fallbackMessage][, asObject])

      • key {string} (required) terms identifier to translate.
      • variableObject {object} (optional) replacement values as object.
      • fallbackMessage {string} (optional) fallback message.
      • asObject {boolean} (optional) return translated result as object instead string. When you need more info about translated result, set this to true.

      Each optional values are omittable.

      this.translate("SAY_HELLO");
      this.translate("SAY_HELLO", true);
      this.translate("SAY_HELLO", { name: "Tom" });
      this.translate("SAY_HELLO", { name: "Tom" }, true);
      this.translate("SAY_HELLO", "Hello, nobody");
      this.translate("SAY_HELLO", "Hello, nobody", true);
      this.translate("SAY_HELLO", { name: "Tom" }, "Hello, nobody");
      this.translate("SAY_HELLO", { name: "Tom" }, "Hello, nobody", true);
      

      Return value will become a translated result with the variables. When translations would be failed(not found terms in all the dictionaries, some error causing, invalid variables, etc.)

      When asObject set as true, the return object would have these properties;

      {
        key, // original seeking term
          variables, // replacement
          asObject, // return value as object or string
          language, // which language is used
          source, // translation template before replacement with variables
          translated, // final translated result
          criteria, // where the dictionary locates ('core' or each module)
          fallback, // fallback message from `.translate()`
          moduleName, // which module call this
          toString(); // toString method. return value will be same with `translated`
      }
      

      In general module developing, this.translate() might be waht all you need to know. But for more control of translator, you can use the below methods.

      Translator.getLanguages()

      It will return current array of language list used in Translator by seeking order. Usually it will be a combination mix of config.language and config.languages.

      Translator.getLocale()

      It will return current locale value. Usually it will be a BCP-47 regulated config.locale. When the user’s locale info is not proper, it will have default as a default value.

      Translator.registerFormatter(formatName, formatFunc)

      • formatName {string} (required) format identifier
      • formatFunc {Function} (required) callback function to format value.
        • formatFunc will get a format object as a parameter when it called.
        • Format object will have this property.
      {
        value,  // original value from replacement variables to format by this formatter
        locale, // If not described in dictionary, default locale value of translator will be used
        ...rest // all other values of user definition in dictionary
      }
      

      With this method, you can add or overwrite global formatter from your module.

      Example

      // in MM-Something module.
      Translator.registerFormatter("TemperatureConverter", function ({ value, locale, options } = {}) {
        if (isNaN(value)) return value;
        if (locale === "en-US") {
          // // just for example of how to use locale.
          options.unit = "°F";
          options.convert = "c2f";
        }
        var unit = options.unit ? options.unit : "";
        if (options.convert) {
          if (options.convert.toLowerCase() === "c2f") return Math.round((value * 9 * 10) / 5) / 10 + 32 + unit;
          if (options.convert.toLowerCase() === "f2c") return Math.round(((value - 32) / 9) * 5 * 10) / 10 + unit;
        }
        return value + unit;
      });
      
      // ...
      
      var translated = this.translate("CURRENT_TEMP", { temp: 22 });
      // It will have 'It is 71.6°F.' as defined in dictionary.
      
      /* in translation file */
      {
        "CURRENT_TEMP": "It is {temp@myTemp}.",
      
        "@myTemp": {
          "format": "TemperatureConverter",
          "options": { "unit": "°F", "convert": "c2f" }
          /* "locale": "en-US" */
        }
      }
      

      Regardless of whatever original locale is, translation provider can set locale to be used frocely for fromatting in this translation when he sets locale.

      Ready-made formats.

      NumberFormat

      Implementation of Intl.NumberFormat - more info

      You can change the number values to various formats for the locale - currency, unit, conversion, separtor grouping, aproximation, etc. See above link.

      • input variable type : number or calculable data (e.g. stringified number - “123”)
      • using properties in translation : options, locale

      Examples of what possible

      • 123456.789 => “123.456,79 €”
      • 123456.789 => “¥ 123,457”
      • 123456.789 => “1,23,000”
      • 3500 => “3,500 liters”
      • -3500 => “-$3,500.00”
      • 987654321 => “988M”

      DateTimeFormat

      Implementation of Intl.DateTimeFormat - more info

      You can change the date values to various formats for the locale - various calendar/date/time/timezone and misc. parts.

      • input variable type : Date object or date-like data (e.g. stringified date - “2021-08-19 12:34:56”)
      • using properties in translation : options, locale

      Examples of what possible

      • 2021-01-23 01:23:45 => “23/01/2021” or “21/01/23 Mon.” or “1 at night”, etc. by locale and format option

      RelativeTimeFormat

      Implementation of Intl.RelativeTimeFormat - more info

      You can convert period to relative humanized format by unit.

      • input variable type : number or calculable data (e.g. stringified number - “123”) as period
      • using properties in translation : options, locale, unit

      Examples of what possible

      • “2 hours ago”, “tomorrow”, “in 3 days”

      RelativeTimeFormat needs base unit to calculate. AutoScaledRelativeTimeFormat will auto calculate unit for convenience. See below.

      AutoScaledRelativeTimeFormat

      Similar to RelativeTimeFormat but unit will be decided automatically. The period is calculated based on the current time.

      • input variable type : Date object or date-like data (e.g. stringified date - “2021-08-19 12:34:56”)
      • using properties in translation : options, locale

      ListFormat

      Implementation of Intl.ListFormat - more info

      You can list items with language-sensitive list formatting.

      • input variable type : array of string
      • using properties in translation : options, locale

      Examples of what possible

      • [‘A’, ‘B’, ‘C’] => “A, B, and C”
      • [‘A’, ‘B’, ‘C’] => “A, B und C”
      • [‘A’, ‘B’, ‘C’] => “A, B oder C”
      • [‘A’, ‘B’, ‘C’] => “A, B, C”
      • [‘A’, ‘B’, ‘C’] => “A B C”

      PluralRules

      Implementation of Intl.PluralRules - more info

      It enables plural-sensitive formatting and plural-related language rules.

      • input variable type : number or calculable data (e.g. stringified number - “123”)
      • using properties in translation : options, locale, rules

      Examples of what possible

      • “I have 1 ball.” / “I have 3 balls.”
      • “1st, 2nd, 3rd, 4th, 11th, 12th, 13th, 21st, 22nd, 23rd”
      /* in translation xx.json */
      {
        "I_HAVE_BALL": "I have {count} ball{count@plural_postfix_s}.",
        "@plural_postfix_s": {
          "format": "PluralRules",
          "options": { "type": "ordinal" },
          "rules": {
            "one": "",
            "other": "s"
          }
        }
      }
      

      Select

      Simple conditional value converter

      • input variable type : string
      • using properties in translation : rules
      /* in translation xx.json */
      {
        "STATUS": "Main job is {status@mySelect}.",
        "@mySelect": {
          "rules": {
            "ONGOING": "processing now",
            "STOP": "stopped",
            "FINISH": "completed",
            "other": "working"
          }
        }
      }
      

      When this formatter cannot find the matched rule with given value, "other" will be used.

      this.translate("STATUS", { status: "ONGOING" });
      // => 'Main job is processing now.'
      this.translate("STATUS", { status: "PREPARED" });
      // => 'Main job is working.'
      

      Current dev status

      • based on MM 2.16 dev (2.17 beta).

      • All spec. described above is implemented.

      • new Unit Test for translator is written and is passed.

        unit test : jest tests/unit/classes/translator_spec.js -i --forceExit

      I haven’t made PR to main MM repository, because;

      • (TODO) e2e test. > but I have no idea how to build it. I need a help.

      • (TODO) Documentation > new trnaslator probably need a documentation for the users. I need a help too, because I’m not a native English user so my skill of writing is not enough.

      • (TODO maybe) Sharing translator for node_helper

      To this moment, I’m not sure whether this project has worthy to be included in main MM project or not. Will this be useful? I’m afraid that I’m the only one who needs these enhanced feature.

      Thanks.

      Seongnoh Yi (eouia0819@gmail.com)

      posted in Feature Requests
      M
      MMRIZE

    Latest posts made by MMRIZE

    • Long time no see and need a help.

      It’s truly been a long time.

      At the beginning of this year, I wrapped up 13 years of business in Frankfurt, Germany, and returned to Seoul, Korea. Due to the move and various other matters, I haven’t been able to focus on this project. However, since February, I’ve started working again—this time in Beijing, China.

      One serious issue is that, for various security-related reasons, it has become extremely difficult to access GitHub, this project, and the community. As you may know, China’s Golden Shield censorship system and the Great Firewall have rendered almost all VPNS useless. It’s not just GitHub—accessing Google, Dropbox, or any external APIS has become very challenging. On top of that, my company’s security policies prevent me from working on external projects during work hours. (and even in my free time… What a situation!)

      As a result, I haven’t been able to maintain many of the MagicMirror modules I developed, let alone respond to GitHub issues.

      Given these circumstances, maintaining my GitHub repositories is extremely difficult.
      If anyone is interested in any of my modules, I would be happy to give them repository management rights. I had a similar absence from this scene in the past, and back then I regrettably transferred full ownership of some modules—which I now deeply regret. This time, I intend to assign co-maintainer rights instead. If you’re interested, please email me (eouia0819@gmail.com). I may have difficulty checking emails, but I’ll try to do so as much as I can.

      I’m not sure when my work in China will end, but I want to express that I still care deeply about this community.

      posted in Forum
      M
      MMRIZE
    • RE: MMM-CalendarExt3 Resize module

      @Xsoldier2000
      This module usually (and for your convenience), uses the whole width of the region that this module lays on. So, if you want to use 3/4 width of the entire screen, it will be easier to limit the width and location of the region itself. So, if you want to lay this module into top_center, guess how to expand and locate top_center region to 3/4 width from the right edge. (There could be many solution and condition, so I cannot point a silver bullet.)

      posted in Custom CSS
      M
      MMRIZE
    • RE: MMM-CalendarExt3 only one calendar not updating

      Hmmm… I was in our traditional ceremony with my family - a lunar new year, so I couldn’t catch this post. Sorry.
      Anyway, this symptom is not my module’s fault, right? There were some reports similar to this, but not figured out.

      posted in Troubleshooting
      M
      MMRIZE
    • RE: MMM-CalendarExt3Agenda on a higher screen resolution?

      @sdetweil
      Thanks for your explanation always.
      I’ll add small message in the screen on waiting - “Waiting calendar fetch…” or something informative in the next update…

      posted in Troubleshooting
      M
      MMRIZE
    • RE: New module installer

      @MDWEBB said in New module installer:

      [ERROR] ReferenceError: HTMLElement is not defined

      This error message seems to be caused by some JS validator trying to check the browser-oriented syntax on the nodeJS environment.

      @MDWEBB
      You’d better start from a clean configuration and then add one by one to find what was wrong.

      posted in General Discussion
      M
      MMRIZE
    • RE: MMM-CalendarExt3 only one calendar not updating

      @oquendo421

      maximumEntries: 4,
      

      Hmmmm… I think you’d better increase this value more.

      posted in Troubleshooting
      M
      MMRIZE
    • RE: MMM-CalendarExt3Agenda

      @rkorell
      Do you have any sketch for AS-IS and TO-BE?

      posted in Utilities
      M
      MMRIZE
    • RE: MMM-CalendarExt3 month header and current date format

      @plainbroke @reverendz
      Instead of .date_xx, use .today to point today’s cell.

      And about the circle; https://forum.magicmirror.builders/topic/18324/mmm-calendarext3-show-color/11?_=1736098133616

      posted in Troubleshooting
      M
      MMRIZE
    • RE: MMM-CalendarExt3Agenda - how to hide days with no events and hide/filter out events with a keywords

      @rkorell
      CX3A is identified with CSS selector “.CX3A” to be distinguished from CX3.

      posted in Troubleshooting
      M
      MMRIZE
    • RE: 2.30.0 and MMM-CalendarExt3 missing calendars

      I think I found it.

      Add these into the default calendar module.

      maximumEntries: 100,
      maximumNumberOfDays: 365,
      

      2f9dec1e-0058-4adf-9dbf-f2ede9db800c-image.png

      posted in Troubleshooting
      M
      MMRIZE