Quarkus GraalVM本机图像DateTimeFormatter和本地化

时间:2020-07-05 18:02:11

标签: date localization quarkus graalvm graalvm-native-image

我试图在Java中使用本地化以本地风格打印日期。 我已经使用数字和货币进行了类似的功能,但到目前为止我仍未应用相同的行为。

几天前GraalVM Quarkus Locale in native mode张贴此主题时,我了解到,在纯模式下使用本地化需要使用创建“ @AutomaticFeature”。

此技巧适用于数字和货币:

import React from "react";
import styled from "styled-components";
import {
  useTable,
  usePagination
} from "react-table";

import {
  FixedSizeList,
  FixedSizeGrid
} from "react-window";

import makeData from "./makeData";

const Styles = styled.div `
  padding: 1rem;

  table {
    border-spacing: 0;
    border: 1px solid black;

    tr {
      :last-child {
        td {
          border-bottom: 0;
        }
      }
    }

    th,
    td {
      margin: 0;
      padding: 0.5rem;
      border-bottom: 1px solid black;
      border-right: 1px solid black;

      :last-child {
        border-right: 0;
      }

      input {
        font-size: 1rem;
        padding: 0;
        margin: 0;
        border: 0;
      }
    }
  }

  .pagination {
    padding: 0.5rem;
  }
`;

// Create an editable cell renderer
const EditableCell = ({
  value: initialValue,
  row: {
    index
  },
  column: {
    id
  },
  updateMyData, // This is a custom function that we supplied to our table instance
}) => {
  // We need to keep and update the state of the cell normally
  const [value, setValue] = React.useState(initialValue);

  const onChange = (e) => {
    setValue(e.target.value);
  };

  // We'll only update the external data when the input is blurred
  const onBlur = () => {
    updateMyData(index, id, value);
  };

  // If the initialValue is changed external, sync it up with our state
  React.useEffect(() => {
    setValue(initialValue);
  }, [initialValue]);

  return <input value = {
    value
  }
  onChange = {
    onChange
  }
  onBlur = {
    onBlur
  }
  />;
};

// Set our editable cell renderer as the default Cell renderer
const defaultColumn = {
  Cell: EditableCell,
};

// Be sure to pass our updateMyData and the skipPageReset option
function Table({
  columns,
  data,
  updateMyData,
  skipPageReset
}) {
  // For this example, we're using pagination to illustrate how to stop
  // the current page from resetting when our data changes
  // Otherwise, nothing is different here.
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,
    totalColumnsWidth,
    page,
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: {
      pageIndex,
      pageSize
    },
  } = useTable({
      columns,
      data,
      defaultColumn,
      // use the skipPageReset option to disable page resetting temporarily
      autoResetPage: !skipPageReset,

      // updateMyData isn't part of the API, but
      // anything we put into these options will
      // automatically be available on the instance.
      // That way we can call this function from our
      // cell renderer!
      updateMyData,
    },
    usePagination
  );

  // Render the UI for your table
  return ( <
    div >
    <
    table { ...getTableProps()
    } >
    <
    thead > {
      headerGroups.map((headerGroup) => ( <
        tr { ...headerGroup.getHeaderGroupProps()
        } > {
          headerGroup.headers.map((column) => ( <
            th { ...column.getHeaderProps()
            } > {
              column.render("Header")
            } < /th>
          ))
        } <
        /tr>
      ))
    } <
    /thead> <
    tbody { ...getTableBodyProps()
    } >
    <
    FixedSizeList height = {
      400
    }
    itemCount = {
      10
    } //test before was {rows.length}
    itemSize = {
      35
    }
    width = {
      totalColumnsWidth
    } >
    {
      page.map((row, i) => {
        prepareRow(row);
        return ( <
          tr { ...row.getRowProps()
          } > {
            row.cells.map((cell) => {
              return ( <
                td { ...cell.getCellProps()
                } > {
                  cell.render("Cell")
                } < /td>
              );
            })
          } <
          /tr>
        );
      })
    } <
    /FixedSizeList> <
    /tbody> <
    /table> <
    div className = "pagination" >
    <
    button onClick = {
      () => gotoPage(0)
    }
    disabled = {!canPreviousPage
    } > {
      "<<"
    } <
    /button>{" "} <
    button onClick = {
      () => previousPage()
    }
    disabled = {!canPreviousPage
    } > {
      "<"
    } <
    /button>{" "} <
    button onClick = {
      () => nextPage()
    }
    disabled = {!canNextPage
    } > {
      ">"
    } <
    /button>{" "} <
    button onClick = {
      () => gotoPage(pageCount - 1)
    }
    disabled = {!canNextPage
    } > {
      ">>"
    } <
    /button>{" "} <
    span >
    Page {
      " "
    } <
    strong > {
      pageIndex + 1
    } of {
      pageOptions.length
    } <
    /strong>{" "} <
    /span> <
    span >
    |
    Go to page: {
      " "
    } <
    input type = "number"
    defaultValue = {
      pageIndex + 1
    }
    onChange = {
      (e) => {
        const page = e.target.value ? Number(e.target.value) - 1 : 0;
        gotoPage(page);
      }
    }
    style = {
      {
        width: "100px"
      }
    }
    /> <
    /span>{" "} <
    select value = {
      pageSize
    }
    onChange = {
      (e) => {
        setPageSize(Number(e.target.value));
      }
    } >
    {
      [10, 20, 30, 40, 50].map((pageSize) => ( <
        option key = {
          pageSize
        }
        value = {
          pageSize
        } >
        Show {
          pageSize
        } <
        /option>
      ))
    } <
    /select> <
    /div> <
    /div>
  );
}

function App() {
  const columns = React.useMemo(
    () => [{
        Header: "Name",
        columns: [{
            Header: "First Name",
            accessor: "firstName",
          },
          {
            Header: "Last Name",
            accessor: "lastName",
          },
        ],
      },
      {
        Header: "Info",
        columns: [{
            Header: "Age",
            accessor: "age",
          },
          {
            Header: "Visits",
            accessor: "visits",
          },
          {
            Header: "Status",
            accessor: "status",
          },
          {
            Header: "Profile Progress",
            accessor: "progress",
          },
        ],
      },
    ], []
  );

  const [data, setData] = React.useState(() => makeData(20));
  const [originalData] = React.useState(data);
  const [skipPageReset, setSkipPageReset] = React.useState(false);

  // We need to keep the table from resetting the pageIndex when we
  // Update data. So we can keep track of that flag with a ref.

  // When our cell renderer calls updateMyData, we'll use
  // the rowIndex, columnId and new value to update the
  // original data
  const updateMyData = (rowIndex, columnId, value) => {
    // We also turn on the flag to not reset the page
    setSkipPageReset(true);
    setData((old) =>
      old.map((row, index) => {
        if (index === rowIndex) {
          return {
            ...old[rowIndex],
            [columnId]: value,
          };
        }
        return row;
      })
    );
  };

  // After data chagnes, we turn the flag back off
  // so that if data actually changes when we're not
  // editing it, the page is reset
  React.useEffect(() => {
    setSkipPageReset(false);
  }, [data]);

  // Let's add a data resetter/randomizer to help
  // illustrate that flow...
  const resetData = () => setData(originalData);

  return ( <
    Styles >
    <
    button onClick = {
      resetData
    } > Reset Data < /button> <
    Table columns = {
      columns
    }
    data = {
      data
    }
    updateMyData = {
      updateMyData
    }
    skipPageReset = {
      skipPageReset
    }
    /> <
    /Styles>
  );
}

export default App;

但它不适用于DateTimeFormatter:

img {
  width: 100%;
}

.navbar {
  background-color: #e3f2fd;
}

.fa.fa-edit {
  color: #18a2b9;
}

.list-group-item.delete:hover {
  cursor: -webkit-grab;
  background-color: pink;
}

.list-group-item.update:hover {
  cursor: -webkit-grab;
  background-color: gainsboro;
}

.list-group-item.board:hover {
  cursor: -webkit-grab;
  background-color: gainsboro;
}

.fa.fa-minus-circle {
  color: red;
}

.landing {
  position: relative;
  /* background: url("../img/showcase.jpg") no-repeat; */
  background-size: cover;
  background-position: center;
  height: 100vh;
  margin-top: -24px;
  margin-bottom: -50px;
}

.landing-inner {
  padding-top: 80px;
}

.dark-overlay {
  background-color: rgba(0, 0, 0, 0.7);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.card-form {
  opacity: 0.9;
}

.latest-profiles-img {
  width: 40px;
  height: 40px;
}

.form-control::placeholder {
  color: #bbb !important;
}

在开发模式下一切正常,但是在纯模式下,语言环境被忽略。样式始终相同,月份名称不翻译。 我在Google上寻找解决方案,但没有找到任何东西,所以我在StackOverflow上询问。

如有需要,我可以为您服务。

关于, 斯特凡。

1 个答案:

答案 0 :(得分:0)

我不明白为什么,但是以下解决方案有效:

public class DateFormatterSupport {

    private Map<Locale, DateTimeFormatter> dateTimeFormatterByLocale;

    public DateFormatterSupport() {
        dateTimeFormatterByLocale = Arrays.stream(Locale.getAvailableLocales()).collect(Collectors.toMap(
            Function.identity(),
            l -> DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(l)));

        Arrays.stream(Locale.getAvailableLocales()).forEach(locale -> {
            dateTimeFormatterByLocale.get(locale).format(LocalDate.now());
        });
    }

    public DateTimeFormatter get(Locale locale) {
        return dateTimeFormatterByLocale.get(locale);
    }

}